You need to sign in or sign up before continuing.
提交 3683243b 编写于 作者: I Ian Campbell 提交者: David S. Miller

xen-netfront: use __pskb_pull_tail to ensure linear area is big enough on RX

I'm slightly concerned by the "only in exceptional circumstances"
comment on __pskb_pull_tail but the structure of an skb just created
by netfront shouldn't hit any of the especially slow cases.

This approach still does slightly more work than the old way, since if
we pull up the entire first frag we now have to shuffle everything
down where before we just received into the right place in the first
place.
Signed-off-by: NIan Campbell <ian.campbell@citrix.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Mel Gorman <mgorman@suse.de>
Cc: xen-devel@lists.xensource.com
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Tested-by: NKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: NKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 072a9c48
......@@ -57,8 +57,7 @@
static const struct ethtool_ops xennet_ethtool_ops;
struct netfront_cb {
struct page *page;
unsigned offset;
int pull_to;
};
#define NETFRONT_SKB_CB(skb) ((struct netfront_cb *)((skb)->cb))
......@@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev,
struct sk_buff *skb;
while ((skb = __skb_dequeue(rxq)) != NULL) {
struct page *page = NETFRONT_SKB_CB(skb)->page;
void *vaddr = page_address(page);
unsigned offset = NETFRONT_SKB_CB(skb)->offset;
memcpy(skb->data, vaddr + offset,
skb_headlen(skb));
int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
__free_page(page);
__pskb_pull_tail(skb, pull_to - skb_headlen(skb));
/* Ethernet work: Delayed to here as it peeks the header. */
skb->protocol = eth_type_trans(skb, dev);
......@@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
struct sk_buff_head errq;
struct sk_buff_head tmpq;
unsigned long flags;
unsigned int len;
int err;
spin_lock(&np->rx_lock);
......@@ -955,24 +947,13 @@ static int xennet_poll(struct napi_struct *napi, int budget)
}
}
NETFRONT_SKB_CB(skb)->page =
skb_frag_page(&skb_shinfo(skb)->frags[0]);
NETFRONT_SKB_CB(skb)->offset = rx->offset;
len = rx->status;
if (len > RX_COPY_THRESHOLD)
len = RX_COPY_THRESHOLD;
skb_put(skb, len);
NETFRONT_SKB_CB(skb)->pull_to = rx->status;
if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
if (rx->status > len) {
skb_shinfo(skb)->frags[0].page_offset =
rx->offset + len;
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
skb->data_len = rx->status - len;
} else {
__skb_fill_page_desc(skb, 0, NULL, 0, 0);
skb_shinfo(skb)->nr_frags = 0;
}
skb_shinfo(skb)->frags[0].page_offset = rx->offset;
skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
skb->data_len = rx->status;
i = xennet_fill_frags(np, skb, &tmpq);
......@@ -999,7 +980,7 @@ static int xennet_poll(struct napi_struct *napi, int budget)
* receive throughout using the standard receive
* buffer size was cut by 25%(!!!).
*/
skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
skb->len += skb->data_len;
if (rx->flags & XEN_NETRXF_csum_blank)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册