Message ID | 1353411606-15940-1-git-send-email-ian.campbell@citrix.com |
---|---|
State | Superseded, archived |
Delegated to: | David Miller |
Headers | show |
>>> On 20.11.12 at 12:40, Ian Campbell <ian.campbell@citrix.com> wrote: > An SKB paged fragment can consist of a compound page with order > 0. > However the netchannel protocol deals only in PAGE_SIZE frames. > > Handle this in xennet_make_frags by iterating over the frames which > make up the page. > > This is the netfront equivalent to 6a8ed462f16b for netback. Wouldn't you need to be at least a little more conservative here with respect to resource use: I realize that get_id_from_freelist() return values were never checked, and failure of gnttab_claim_grant_reference() was always dealt with via BUG_ON(), but considering that netfront_tx_slot_available() doesn't account for compound page fragments, I think this (lack of) error handling needs improvement in the course of the change here (regardless of - I think - someone having said that usually the sum of all pages referenced from an skb's fragments would not exceed MAX_SKB_FRAGS - "usually" just isn't enough imo). Jan > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Cc: netdev@vger.kernel.org > Cc: xen-devel@lists.xen.org > Cc: Eric Dumazet <edumazet@google.com> > Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> > Cc: ANNIE LI <annie.li@oracle.com> > Cc: Sander Eikelenboom <linux@eikelenboom.it> > Cc: Stefan Bader <stefan.bader@canonical.com> > --- > drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- > 1 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > index caa0110..a12b99a 100644 > --- a/drivers/net/xen-netfront.c > +++ b/drivers/net/xen-netfront.c > @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, > struct net_device *dev, > /* Grant backend access to each skb fragment page. */ > for (i = 0; i < frags; i++) { > skb_frag_t *frag = skb_shinfo(skb)->frags + i; > + struct page *page = skb_frag_page(frag); > + unsigned long size = skb_frag_size(frag); > + unsigned long offset = frag->page_offset; > > - tx->flags |= XEN_NETTXF_more_data; > + /* Data must not cross a page boundary. */ > + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); > > - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > - np->tx_skbs[id].skb = skb_get(skb); > - tx = RING_GET_REQUEST(&np->tx, prod++); > - tx->id = id; > - ref = gnttab_claim_grant_reference(&np->gref_tx_head); > - BUG_ON((signed short)ref < 0); > + /* Skip unused frames from start of page */ > + page += offset >> PAGE_SHIFT; > + offset &= ~PAGE_MASK; > > - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); > - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > - mfn, GNTMAP_readonly); > + while (size > 0) { > + unsigned long bytes; > > - tx->gref = np->grant_tx_ref[id] = ref; > - tx->offset = frag->page_offset; > - tx->size = skb_frag_size(frag); > - tx->flags = 0; > + BUG_ON(offset >= PAGE_SIZE); > + > + bytes = PAGE_SIZE - offset; > + if (bytes > size) > + bytes = size; > + > + tx->flags |= XEN_NETTXF_more_data; > + > + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > + np->tx_skbs[id].skb = skb_get(skb); > + tx = RING_GET_REQUEST(&np->tx, prod++); > + tx->id = id; > + ref = gnttab_claim_grant_reference(&np->gref_tx_head); > + BUG_ON((signed short)ref < 0); > + > + mfn = pfn_to_mfn(page_to_pfn(page)); > + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > + mfn, GNTMAP_readonly); > + > + tx->gref = np->grant_tx_ref[id] = ref; > + tx->offset = offset; > + tx->size = bytes; > + tx->flags = 0; > + > + offset += bytes; > + size -= bytes; > + > + /* Next frame */ > + if (offset == PAGE_SIZE && size) { > + BUG_ON(!PageCompound(page)); > + page++; > + offset = 0; > + } > + } > } > > np->tx.req_prod_pvt = prod; > -- > 1.7.2.5 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Aside from Jans comments about error handling, I tried below patch and it seems to solve the problem with transfers out of the domU for me (though only shallow testing done, otoh 5 times is more than getting stuck the first time). -Stefan On 20.11.2012 12:40, Ian Campbell wrote: > An SKB paged fragment can consist of a compound page with order > 0. > However the netchannel protocol deals only in PAGE_SIZE frames. > > Handle this in xennet_make_frags by iterating over the frames which > make up the page. > > This is the netfront equivalent to 6a8ed462f16b for netback. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Cc: netdev@vger.kernel.org > Cc: xen-devel@lists.xen.org > Cc: Eric Dumazet <edumazet@google.com> > Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> > Cc: ANNIE LI <annie.li@oracle.com> > Cc: Sander Eikelenboom <linux@eikelenboom.it> > Cc: Stefan Bader <stefan.bader@canonical.com> Tested-by: Stefan Bader <stefan.bader@canonical.com> > --- > drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- > 1 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > index caa0110..a12b99a 100644 > --- a/drivers/net/xen-netfront.c > +++ b/drivers/net/xen-netfront.c > @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, > /* Grant backend access to each skb fragment page. */ > for (i = 0; i < frags; i++) { > skb_frag_t *frag = skb_shinfo(skb)->frags + i; > + struct page *page = skb_frag_page(frag); > + unsigned long size = skb_frag_size(frag); > + unsigned long offset = frag->page_offset; > > - tx->flags |= XEN_NETTXF_more_data; > + /* Data must not cross a page boundary. */ > + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); > > - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > - np->tx_skbs[id].skb = skb_get(skb); > - tx = RING_GET_REQUEST(&np->tx, prod++); > - tx->id = id; > - ref = gnttab_claim_grant_reference(&np->gref_tx_head); > - BUG_ON((signed short)ref < 0); > + /* Skip unused frames from start of page */ > + page += offset >> PAGE_SHIFT; > + offset &= ~PAGE_MASK; > > - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); > - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > - mfn, GNTMAP_readonly); > + while (size > 0) { > + unsigned long bytes; > > - tx->gref = np->grant_tx_ref[id] = ref; > - tx->offset = frag->page_offset; > - tx->size = skb_frag_size(frag); > - tx->flags = 0; > + BUG_ON(offset >= PAGE_SIZE); > + > + bytes = PAGE_SIZE - offset; > + if (bytes > size) > + bytes = size; > + > + tx->flags |= XEN_NETTXF_more_data; > + > + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > + np->tx_skbs[id].skb = skb_get(skb); > + tx = RING_GET_REQUEST(&np->tx, prod++); > + tx->id = id; > + ref = gnttab_claim_grant_reference(&np->gref_tx_head); > + BUG_ON((signed short)ref < 0); > + > + mfn = pfn_to_mfn(page_to_pfn(page)); > + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > + mfn, GNTMAP_readonly); > + > + tx->gref = np->grant_tx_ref[id] = ref; > + tx->offset = offset; > + tx->size = bytes; > + tx->flags = 0; > + > + offset += bytes; > + size -= bytes; > + > + /* Next frame */ > + if (offset == PAGE_SIZE && size) { > + BUG_ON(!PageCompound(page)); > + page++; > + offset = 0; > + } > + } > } > > np->tx.req_prod_pvt = prod; >
Tuesday, November 20, 2012, 2:30:54 PM, you wrote: > Aside from Jans comments about error handling, I tried below patch and it seems > to solve the problem with transfers out of the domU for me (though only shallow > testing done, otoh 5 times is more than getting stuck the first time). > -Stefan I'm running with this patch now, it seems to fix the problems for me as well. -- Sander > On 20.11.2012 12:40, Ian Campbell wrote: >> An SKB paged fragment can consist of a compound page with order > 0. >> However the netchannel protocol deals only in PAGE_SIZE frames. >> >> Handle this in xennet_make_frags by iterating over the frames which >> make up the page. >> >> This is the netfront equivalent to 6a8ed462f16b for netback. >> >> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> >> Cc: netdev@vger.kernel.org >> Cc: xen-devel@lists.xen.org >> Cc: Eric Dumazet <edumazet@google.com> >> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> >> Cc: ANNIE LI <annie.li@oracle.com> >> Cc: Sander Eikelenboom <linux@eikelenboom.it> >> Cc: Stefan Bader <stefan.bader@canonical.com> > Tested-by: Stefan Bader <stefan.bader@canonical.com> >> --- >> drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- >> 1 files changed, 44 insertions(+), 14 deletions(-) >> >> diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c >> index caa0110..a12b99a 100644 >> --- a/drivers/net/xen-netfront.c >> +++ b/drivers/net/xen-netfront.c >> @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, >> /* Grant backend access to each skb fragment page. */ >> for (i = 0; i < frags; i++) { >> skb_frag_t *frag = skb_shinfo(skb)->frags + i; >> + struct page *page = skb_frag_page(frag); >> + unsigned long size = skb_frag_size(frag); >> + unsigned long offset = frag->page_offset; >> >> - tx->flags |= XEN_NETTXF_more_data; >> + /* Data must not cross a page boundary. */ >> + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); >> >> - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); >> - np->tx_skbs[id].skb = skb_get(skb); >> - tx = RING_GET_REQUEST(&np->tx, prod++); >> - tx->id = id; >> - ref = gnttab_claim_grant_reference(&np->gref_tx_head); >> - BUG_ON((signed short)ref < 0); >> + /* Skip unused frames from start of page */ >> + page += offset >> PAGE_SHIFT; >> + offset &= ~PAGE_MASK; >> >> - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); >> - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, >> - mfn, GNTMAP_readonly); >> + while (size > 0) { >> + unsigned long bytes; >> >> - tx->gref = np->grant_tx_ref[id] = ref; >> - tx->offset = frag->page_offset; >> - tx->size = skb_frag_size(frag); >> - tx->flags = 0; >> + BUG_ON(offset >= PAGE_SIZE); >> + >> + bytes = PAGE_SIZE - offset; >> + if (bytes > size) >> + bytes = size; >> + >> + tx->flags |= XEN_NETTXF_more_data; >> + >> + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); >> + np->tx_skbs[id].skb = skb_get(skb); >> + tx = RING_GET_REQUEST(&np->tx, prod++); >> + tx->id = id; >> + ref = gnttab_claim_grant_reference(&np->gref_tx_head); >> + BUG_ON((signed short)ref < 0); >> + >> + mfn = pfn_to_mfn(page_to_pfn(page)); >> + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, >> + mfn, GNTMAP_readonly); >> + >> + tx->gref = np->grant_tx_ref[id] = ref; >> + tx->offset = offset; >> + tx->size = bytes; >> + tx->flags = 0; >> + >> + offset += bytes; >> + size -= bytes; >> + >> + /* Next frame */ >> + if (offset == PAGE_SIZE && size) { >> + BUG_ON(!PageCompound(page)); >> + page++; >> + offset = 0; >> + } >> + } >> } >> >> np->tx.req_prod_pvt = prod; >> -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, 2012-11-20 at 11:40 +0000, Ian Campbell wrote: > An SKB paged fragment can consist of a compound page with order > 0. > However the netchannel protocol deals only in PAGE_SIZE frames. > > Handle this in xennet_make_frags by iterating over the frames which > make up the page. > > This is the netfront equivalent to 6a8ed462f16b for netback. > > Signed-off-by: Ian Campbell <ian.campbell@citrix.com> > Cc: netdev@vger.kernel.org > Cc: xen-devel@lists.xen.org > Cc: Eric Dumazet <edumazet@google.com> > Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> > Cc: ANNIE LI <annie.li@oracle.com> > Cc: Sander Eikelenboom <linux@eikelenboom.it> > Cc: Stefan Bader <stefan.bader@canonical.com> > --- > drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- > 1 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > index caa0110..a12b99a 100644 > --- a/drivers/net/xen-netfront.c > +++ b/drivers/net/xen-netfront.c > @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, > /* Grant backend access to each skb fragment page. */ > for (i = 0; i < frags; i++) { > skb_frag_t *frag = skb_shinfo(skb)->frags + i; > + struct page *page = skb_frag_page(frag); > + unsigned long size = skb_frag_size(frag); > + unsigned long offset = frag->page_offset; > > - tx->flags |= XEN_NETTXF_more_data; > + /* Data must not cross a page boundary. */ > + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); > > - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > - np->tx_skbs[id].skb = skb_get(skb); > - tx = RING_GET_REQUEST(&np->tx, prod++); > - tx->id = id; > - ref = gnttab_claim_grant_reference(&np->gref_tx_head); > - BUG_ON((signed short)ref < 0); > + /* Skip unused frames from start of page */ 'frame' in the comment means an order-0 page ? > + page += offset >> PAGE_SHIFT; > + offset &= ~PAGE_MASK; > > - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); > - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > - mfn, GNTMAP_readonly); > + while (size > 0) { > + unsigned long bytes; > > - tx->gref = np->grant_tx_ref[id] = ref; > - tx->offset = frag->page_offset; > - tx->size = skb_frag_size(frag); > - tx->flags = 0; > + BUG_ON(offset >= PAGE_SIZE); > + > + bytes = PAGE_SIZE - offset; > + if (bytes > size) > + bytes = size; > + > + tx->flags |= XEN_NETTXF_more_data; > + > + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > + np->tx_skbs[id].skb = skb_get(skb); BTW this skb_get() means extra atomic operations for every 4096 bytes unit, and an extra atomic op (and test for final 0) at TX completion. This could be avoided, by setting np->tx_skbs[id].skb = skb only for the very last unit. > + tx = RING_GET_REQUEST(&np->tx, prod++); > + tx->id = id; > + ref = gnttab_claim_grant_reference(&np->gref_tx_head); > + BUG_ON((signed short)ref < 0); > + > + mfn = pfn_to_mfn(page_to_pfn(page)); > + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > + mfn, GNTMAP_readonly); > + > + tx->gref = np->grant_tx_ref[id] = ref; > + tx->offset = offset; > + tx->size = bytes; > + tx->flags = 0; > + > + offset += bytes; > + size -= bytes; > + > + /* Next frame */ > + if (offset == PAGE_SIZE && size) { > + BUG_ON(!PageCompound(page)); > + page++; > + offset = 0; > + } > + } > } > > np->tx.req_prod_pvt = prod; Acked-by: Eric Dumazet <edumazet@google.com> Thanks ! -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tue, 2012-11-20 at 14:45 +0000, Eric Dumazet wrote: > > + /* Skip unused frames from start of page */ > > 'frame' in the comment means an order-0 page ? Yes. Confusing in the context of a network driver I know! I couldn't think of a better term. > > + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > > + np->tx_skbs[id].skb = skb_get(skb); > > BTW this skb_get() means extra atomic operations for every 4096 bytes > unit, and an extra atomic op (and test for final 0) at TX completion. > This could be avoided, by setting np->tx_skbs[id].skb = skb only for the > very last unit. Thanks. Might be tricky because guests can ack the individual requests in any order but it's something worth having a look at. > > np->tx.req_prod_pvt = prod; > > Acked-by: Eric Dumazet <edumazet@google.com> > > Thanks ! Thanks for the review. Ian. > > -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2012-11-20 19:40, Ian Campbell wrote: > An SKB paged fragment can consist of a compound page with order> 0. > However the netchannel protocol deals only in PAGE_SIZE frames. > > Handle this in xennet_make_frags by iterating over the frames which > make up the page. > > This is the netfront equivalent to 6a8ed462f16b for netback. > > Signed-off-by: Ian Campbell<ian.campbell@citrix.com> > Cc: netdev@vger.kernel.org > Cc: xen-devel@lists.xen.org > Cc: Eric Dumazet<edumazet@google.com> > Cc: Konrad Rzeszutek Wilk<konrad@kernel.org> > Cc: ANNIE LI<annie.li@oracle.com> > Cc: Sander Eikelenboom<linux@eikelenboom.it> > Cc: Stefan Bader<stefan.bader@canonical.com> > --- > drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- > 1 files changed, 44 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > index caa0110..a12b99a 100644 > --- a/drivers/net/xen-netfront.c > +++ b/drivers/net/xen-netfront.c > @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, > /* Grant backend access to each skb fragment page. */ > for (i = 0; i< frags; i++) { > skb_frag_t *frag = skb_shinfo(skb)->frags + i; > + struct page *page = skb_frag_page(frag); > + unsigned long size = skb_frag_size(frag); > + unsigned long offset = frag->page_offset; There are following definitions at the beginning of xennet_make_frags, unsigned int offset = offset_in_page(data); unsigned int len = skb_headlen(skb); Is it better to reuse those definitions, and not define new size and offset again in this for loop? And unsigned int is enough here, right? > > - tx->flags |= XEN_NETTXF_more_data; > + /* Data must not cross a page boundary. */ > + BUG_ON(size + offset> PAGE_SIZE<<compound_order(page)); > > - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); > - np->tx_skbs[id].skb = skb_get(skb); > - tx = RING_GET_REQUEST(&np->tx, prod++); > - tx->id = id; > - ref = gnttab_claim_grant_reference(&np->gref_tx_head); > - BUG_ON((signed short)ref< 0); > + /* Skip unused frames from start of page */ > + page += offset>> PAGE_SHIFT; > + offset&= ~PAGE_MASK; > > - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); > - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > - mfn, GNTMAP_readonly); > + while (size> 0) { > + unsigned long bytes; > > - tx->gref = np->grant_tx_ref[id] = ref; > - tx->offset = frag->page_offset; > - tx->size = skb_frag_size(frag); > - tx->flags = 0; > + BUG_ON(offset>= PAGE_SIZE); > + > + bytes = PAGE_SIZE - offset; > + if (bytes> size) > + bytes = size; > + > + tx->flags |= XEN_NETTXF_more_data; > + > + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); Over 80 characters? > + np->tx_skbs[id].skb = skb_get(skb); > + tx = RING_GET_REQUEST(&np->tx, prod++); > + tx->id = id; > + ref = gnttab_claim_grant_reference(&np->gref_tx_head); > + BUG_ON((signed short)ref< 0); > + > + mfn = pfn_to_mfn(page_to_pfn(page)); > + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, > + mfn, GNTMAP_readonly); Over 80 characters? Thanks Annie > + > + tx->gref = np->grant_tx_ref[id] = ref; > + tx->offset = offset; > + tx->size = bytes; > + tx->flags = 0; > + > + offset += bytes; > + size -= bytes; > + > + /* Next frame */ > + if (offset == PAGE_SIZE&& size) { > + BUG_ON(!PageCompound(page)); > + page++; > + offset = 0; > + } > + } > } > > np->tx.req_prod_pvt = prod; -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, 2012-11-21 at 02:52 +0000, ANNIE LI wrote: > > On 2012-11-20 19:40, Ian Campbell wrote: > > An SKB paged fragment can consist of a compound page with order> 0. > > However the netchannel protocol deals only in PAGE_SIZE frames. > > > > Handle this in xennet_make_frags by iterating over the frames which > > make up the page. > > > > This is the netfront equivalent to 6a8ed462f16b for netback. > > > > Signed-off-by: Ian Campbell<ian.campbell@citrix.com> > > Cc: netdev@vger.kernel.org > > Cc: xen-devel@lists.xen.org > > Cc: Eric Dumazet<edumazet@google.com> > > Cc: Konrad Rzeszutek Wilk<konrad@kernel.org> > > Cc: ANNIE LI<annie.li@oracle.com> > > Cc: Sander Eikelenboom<linux@eikelenboom.it> > > Cc: Stefan Bader<stefan.bader@canonical.com> > > --- > > drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- > > 1 files changed, 44 insertions(+), 14 deletions(-) > > > > diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c > > index caa0110..a12b99a 100644 > > --- a/drivers/net/xen-netfront.c > > +++ b/drivers/net/xen-netfront.c > > @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, > > /* Grant backend access to each skb fragment page. */ > > for (i = 0; i< frags; i++) { > > skb_frag_t *frag = skb_shinfo(skb)->frags + i; > > + struct page *page = skb_frag_page(frag); > > + unsigned long size = skb_frag_size(frag); > > + unsigned long offset = frag->page_offset; > > There are following definitions at the beginning of xennet_make_frags, > > unsigned int offset = offset_in_page(data); > unsigned int len = skb_headlen(skb); So they are, well spotted. > Is it better to reuse those definitions, and not define new size and > offset again in this for loop? And unsigned int is enough here, right? Yes to both. > [...] > Over 80 characters? [...] > Over 80 characters? Both fixed, thanks for your review. Ian. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index caa0110..a12b99a 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -452,24 +452,54 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, /* Grant backend access to each skb fragment page. */ for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; + struct page *page = skb_frag_page(frag); + unsigned long size = skb_frag_size(frag); + unsigned long offset = frag->page_offset; - tx->flags |= XEN_NETTXF_more_data; + /* Data must not cross a page boundary. */ + BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); - np->tx_skbs[id].skb = skb_get(skb); - tx = RING_GET_REQUEST(&np->tx, prod++); - tx->id = id; - ref = gnttab_claim_grant_reference(&np->gref_tx_head); - BUG_ON((signed short)ref < 0); + /* Skip unused frames from start of page */ + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, - mfn, GNTMAP_readonly); + while (size > 0) { + unsigned long bytes; - tx->gref = np->grant_tx_ref[id] = ref; - tx->offset = frag->page_offset; - tx->size = skb_frag_size(frag); - tx->flags = 0; + BUG_ON(offset >= PAGE_SIZE); + + bytes = PAGE_SIZE - offset; + if (bytes > size) + bytes = size; + + tx->flags |= XEN_NETTXF_more_data; + + id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); + np->tx_skbs[id].skb = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(page)); + gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = bytes; + tx->flags = 0; + + offset += bytes; + size -= bytes; + + /* Next frame */ + if (offset == PAGE_SIZE && size) { + BUG_ON(!PageCompound(page)); + page++; + offset = 0; + } + } } np->tx.req_prod_pvt = prod;
An SKB paged fragment can consist of a compound page with order > 0. However the netchannel protocol deals only in PAGE_SIZE frames. Handle this in xennet_make_frags by iterating over the frames which make up the page. This is the netfront equivalent to 6a8ed462f16b for netback. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Cc: netdev@vger.kernel.org Cc: xen-devel@lists.xen.org Cc: Eric Dumazet <edumazet@google.com> Cc: Konrad Rzeszutek Wilk <konrad@kernel.org> Cc: ANNIE LI <annie.li@oracle.com> Cc: Sander Eikelenboom <linux@eikelenboom.it> Cc: Stefan Bader <stefan.bader@canonical.com> --- drivers/net/xen-netfront.c | 58 +++++++++++++++++++++++++++++++++---------- 1 files changed, 44 insertions(+), 14 deletions(-)