|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH RFC] xen-netback: coalesce frags before copying
On Fri, 2013-03-15 at 13:25 +0000, Ian Campbell wrote:
> > > > - for (i = start; i < shinfo->nr_frags; i++, txp++) {
> > > > - struct page *page;
> > > > - pending_ring_idx_t index;
> > > > + /* Coalesce */
> > > > + total_frags_merged = 0;
> > > > + for (i = j = start; i < MAX_SKB_FRAGS && j < nr_frags; i++) {
> > >
> > > I can't see any code which causes us to drop the frag if we end up with
> > > i >= MAX_SKB_FRAGS? Is it just too subtle for me?
> > >
> >
> > The basic assumption that it is not possible to reach i >= MAX_SKB_FRAGS
> > since the maximum packet size supported in backend is 64K and we can
> > always accommodate a packet. Any packet larger than 64K causes fatal
> > error early on.
>
> Does that early check also account for frontends which lie in the
> initial slot->size or is that otherwise caught later too? i.e. do we do
> the right thing when there are more bytes in the additional slots than
> the initially header said there would be? I expect we already do, I just
> want to be sure this doesn't subtly alter the conditions.
>
We already do that in netbk_count_requests().
> > I could remove "i < MAX_SKB_FRAGS" if this causes confusion, it is just
> > a redundant check.
>
> Is it an actual invariant? i.e. could it be BUG_ON?
>
Yes. I've added BUG_ON(shinfo->nr_frags > MAX_SKB_FRAGS) before
returning to caller.
> > > > + gop->flags = GNTCOPY_source_gref;
> > > > +
> > > > + gop->source.u.ref = txp->gref;
> > > > + gop->source.domid = vif->domid;
> > > > + gop->source.offset = txp->offset;
> > > > +
> > > > + gop->dest.domid = DOMID_SELF;
> > > > +
> > > > + gop->dest.offset = dst_offset;
> > > > + gop->dest.u.gmfn =
> > > > virt_to_mfn(page_address(page));
> > > > +
> > > > + if (dst_offset + txp->size > PAGE_SIZE) {
> > > > + /* This page can only merge a portion
> > > > of txp */
> > > > + gop->len = PAGE_SIZE - dst_offset;
> > > > + txp->offset += gop->len;
> > > > + txp->size -= gop->len;
> > > > + dst_offset += gop->len; /* ==
> > > > PAGE_SIZE, will quit loop */
> > >
> > > In this case we don't touch pending_cons etc? Is that because when we
> > > hit this case we always go around again and will eventually hit the else
> > > case below ensuring we do the pending_cons stuff exactly once for the
> > > tail end of the buffer? I think that is OK but it is worthy of a
> > > comment.
> > >
> >
> > Yes, we cannot touch pending_cons in this case, because this slot needs
> > to be coped with in next loop, using another gop.
> >
> > > What happens if we hit SKB_FRAG_MAX right as we hit this case? Might we
> > > fail to respond to the final request which has been split in this way?
> > >
> >
> > As stated above, we won't hit i >= MAX_SKB_FRAGS.
>
> OK, same question for i == MAX_SKB_FRAGS - 1 then ;-) Or whatever
> condition would be needed for us to exit here without ever getting to
> this else clause.
>
If we exit outer for-loop before processing all tx requests for a
packet, that means this packet is larger than 64K. But at this point,
we've already know that this packet will not be larger than 64K.
After removing "i < MAX_SKB_FRAGS" check, we can only exit the for-loop
given that we finish processing all tx requests for a packet. And the
counter only decrements after we finish processing a tx request in the
'else' clause.
Wei.
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |