aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netback
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@citrix.com>2014-07-18 14:08:02 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-20 23:56:05 -0400
commit1a998d3e6bc1e44f4c0bc7509bdedef8ed3845ec (patch)
tree343f6de6312d5fa186b808a800bff404a2047367 /drivers/net/xen-netback
parent7801db8aec957fa6610efe0ee26a6c8bc0f1d73b (diff)
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: Zoltan Kiss <zoltan.kiss@citrix.com> Reported-by: Armin 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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netback')
-rw-r--r--drivers/net/xen-netback/netback.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 1844a47636b6..a773f2016bad 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1030,10 +1030,16 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
1030{ 1030{
1031 struct gnttab_map_grant_ref *gop_map = *gopp_map; 1031 struct gnttab_map_grant_ref *gop_map = *gopp_map;
1032 u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx; 1032 u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
1033 /* This always points to the shinfo of the skb being checked, which
1034 * could be either the first or the one on the frag_list
1035 */
1033 struct skb_shared_info *shinfo = skb_shinfo(skb); 1036 struct skb_shared_info *shinfo = skb_shinfo(skb);
1037 /* If this is non-NULL, we are currently checking the frag_list skb, and
1038 * this points to the shinfo of the first one
1039 */
1040 struct skb_shared_info *first_shinfo = NULL;
1034 int nr_frags = shinfo->nr_frags; 1041 int nr_frags = shinfo->nr_frags;
1035 int i, err; 1042 int i, err;
1036 struct sk_buff *first_skb = NULL;
1037 1043
1038 /* Check status of header. */ 1044 /* Check status of header. */
1039 err = (*gopp_copy)->status; 1045 err = (*gopp_copy)->status;
@@ -1086,31 +1092,28 @@ check_frags:
1086 xenvif_idx_unmap(queue, pending_idx); 1092 xenvif_idx_unmap(queue, pending_idx);
1087 } 1093 }
1088 1094
1095 /* And if we found the error while checking the frag_list, unmap
1096 * the first skb's frags
1097 */
1098 if (first_shinfo) {
1099 for (j = 0; j < first_shinfo->nr_frags; j++) {
1100 pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]);
1101 xenvif_idx_unmap(queue, pending_idx);
1102 }
1103 }
1104
1089 /* Remember the error: invalidate all subsequent fragments. */ 1105 /* Remember the error: invalidate all subsequent fragments. */
1090 err = newerr; 1106 err = newerr;
1091 } 1107 }
1092 1108
1093 if (skb_has_frag_list(skb)) { 1109 if (skb_has_frag_list(skb) && !first_shinfo) {
1094 first_skb = skb; 1110 first_shinfo = skb_shinfo(skb);
1095 skb = shinfo->frag_list; 1111 shinfo = skb_shinfo(skb_shinfo(skb)->frag_list);
1096 shinfo = skb_shinfo(skb);
1097 nr_frags = shinfo->nr_frags; 1112 nr_frags = shinfo->nr_frags;
1098 1113
1099 goto check_frags; 1114 goto check_frags;
1100 } 1115 }
1101 1116
1102 /* There was a mapping error in the frag_list skb. We have to unmap
1103 * the first skb's frags
1104 */
1105 if (first_skb && err) {
1106 int j;
1107 shinfo = skb_shinfo(first_skb);
1108 for (j = 0; j < shinfo->nr_frags; j++) {
1109 pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
1110 xenvif_idx_unmap(queue, pending_idx);
1111 }
1112 }
1113
1114 *gopp_map = gop_map; 1117 *gopp_map = gop_map;
1115 return err; 1118 return err;
1116} 1119}