提交 1a998d3e 编写于 作者: Z Zoltan Kiss 提交者: David S. Miller

xen-netback: Fix handling frag_list on grant op error path

The error handling for skb's with frag_list was completely wrong, it caused
double unmap attempts to happen if the error was on the first skb. Move it to
the right place in the loop.
Signed-off-by: NZoltan Kiss <zoltan.kiss@citrix.com>
Reported-by: NArmin Zentai <armin.zentai@ezit.hu>
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: xen-devel@lists.xenproject.org
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 7801db8a
...@@ -1030,10 +1030,16 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue, ...@@ -1030,10 +1030,16 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
{ {
struct gnttab_map_grant_ref *gop_map = *gopp_map; struct gnttab_map_grant_ref *gop_map = *gopp_map;
u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx; u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
/* This always points to the shinfo of the skb being checked, which
* could be either the first or the one on the frag_list
*/
struct skb_shared_info *shinfo = skb_shinfo(skb); struct skb_shared_info *shinfo = skb_shinfo(skb);
/* If this is non-NULL, we are currently checking the frag_list skb, and
* this points to the shinfo of the first one
*/
struct skb_shared_info *first_shinfo = NULL;
int nr_frags = shinfo->nr_frags; int nr_frags = shinfo->nr_frags;
int i, err; int i, err;
struct sk_buff *first_skb = NULL;
/* Check status of header. */ /* Check status of header. */
err = (*gopp_copy)->status; err = (*gopp_copy)->status;
...@@ -1086,31 +1092,28 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue, ...@@ -1086,31 +1092,28 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
xenvif_idx_unmap(queue, pending_idx); xenvif_idx_unmap(queue, pending_idx);
} }
/* And if we found the error while checking the frag_list, unmap
* the first skb's frags
*/
if (first_shinfo) {
for (j = 0; j < first_shinfo->nr_frags; j++) {
pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]);
xenvif_idx_unmap(queue, pending_idx);
}
}
/* Remember the error: invalidate all subsequent fragments. */ /* Remember the error: invalidate all subsequent fragments. */
err = newerr; err = newerr;
} }
if (skb_has_frag_list(skb)) { if (skb_has_frag_list(skb) && !first_shinfo) {
first_skb = skb; first_shinfo = skb_shinfo(skb);
skb = shinfo->frag_list; shinfo = skb_shinfo(skb_shinfo(skb)->frag_list);
shinfo = skb_shinfo(skb);
nr_frags = shinfo->nr_frags; nr_frags = shinfo->nr_frags;
goto check_frags; goto check_frags;
} }
/* There was a mapping error in the frag_list skb. We have to unmap
* the first skb's frags
*/
if (first_skb && err) {
int j;
shinfo = skb_shinfo(first_skb);
for (j = 0; j < shinfo->nr_frags; j++) {
pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
xenvif_idx_unmap(queue, pending_idx);
}
}
*gopp_map = gop_map; *gopp_map = gop_map;
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册