linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop
@ 2014-07-18 18:08 Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 1/4 v2] xen-netback: Fix handling frag_list on grant op error path Zoltan Kiss
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-07-18 18:08 UTC (permalink / raw)
  To: Wei Liu, Ian Campbell; +Cc: Zoltan Kiss, netdev, linux-kernel, xen-devel

This series fixes a lot of bugs on the error path around this function, which
were introduced with my grant mapping series in 3.15. They apply to the latest
net tree, but probably to net-next as well without any modification.
I'll post an another series which applies to 3.15 stable, as the problem was
first discovered there. The only difference is that the "queue" variable name is
replaced to "vif".

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


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH net 1/4 v2] xen-netback: Fix handling frag_list on grant op error path
  2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
@ 2014-07-18 18:08 ` Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 2/4 v2] xen-netback: Fix releasing frag_list skbs in " Zoltan Kiss
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-07-18 18:08 UTC (permalink / raw)
  To: Wei Liu, Ian Campbell; +Cc: Zoltan Kiss, netdev, linux-kernel, xen-devel

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
---
v2: grammar change in comment

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 1844a47..a773f20 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,
 {
 	struct gnttab_map_grant_ref *gop_map = *gopp_map;
 	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);
+	/* 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 i, err;
-	struct sk_buff *first_skb = NULL;
 
 	/* Check status of header. */
 	err = (*gopp_copy)->status;
@@ -1086,31 +1092,28 @@ check_frags:
 			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. */
 		err = newerr;
 	}
 
-	if (skb_has_frag_list(skb)) {
-		first_skb = skb;
-		skb = shinfo->frag_list;
-		shinfo = skb_shinfo(skb);
+	if (skb_has_frag_list(skb) && !first_shinfo) {
+		first_shinfo = skb_shinfo(skb);
+		shinfo = skb_shinfo(skb_shinfo(skb)->frag_list);
 		nr_frags = shinfo->nr_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;
 	return err;
 }

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net 2/4 v2] xen-netback: Fix releasing frag_list skbs in error path
  2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 1/4 v2] xen-netback: Fix handling frag_list on grant op error path Zoltan Kiss
@ 2014-07-18 18:08 ` Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 3/4 v2] xen-netback: Fix releasing header slot on " Zoltan Kiss
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-07-18 18:08 UTC (permalink / raw)
  To: Wei Liu, Ian Campbell; +Cc: Zoltan Kiss, netdev, linux-kernel, xen-devel

When the grant operations failed, the skb is freed up eventually, and it tries
to release the frags, if there is any. For the main skb nr_frags is set to 0 to
avoid this, but on the frag_list it iterates through the frags array, and tries
to call put_page on the page pointer which contains garbage at that time.

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
---
v2: adding comment
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index a773f20..8cbf60d 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1521,7 +1521,16 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
 
 		/* Check the remap error code. */
 		if (unlikely(xenvif_tx_check_gop(queue, skb, &gop_map, &gop_copy))) {
+			/* If there was an error, xenvif_tx_check_gop is
+			 * expected to release all the frags which were mapped,
+			 * so kfree_skb shouldn't do it again
+			 */
 			skb_shinfo(skb)->nr_frags = 0;
+			if (skb_has_frag_list(skb)) {
+				struct sk_buff *nskb =
+						skb_shinfo(skb)->frag_list;
+				skb_shinfo(nskb)->nr_frags = 0;
+			}
 			kfree_skb(skb);
 			continue;
 		}

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net 3/4 v2] xen-netback: Fix releasing header slot on error path
  2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 1/4 v2] xen-netback: Fix handling frag_list on grant op error path Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 2/4 v2] xen-netback: Fix releasing frag_list skbs in " Zoltan Kiss
@ 2014-07-18 18:08 ` Zoltan Kiss
  2014-07-18 18:08 ` [PATCH net 4/4 v2] xen-netback: Fix pointer incrementation to avoid incorrect logging Zoltan Kiss
  2014-07-21  3:57 ` [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-07-18 18:08 UTC (permalink / raw)
  To: Wei Liu, Ian Campbell; +Cc: Zoltan Kiss, netdev, linux-kernel, xen-devel

This patch makes this function aware that the first frag and the header might
share the same ring slot. That could happen if the first slot is bigger than
PKT_PROT_LEN. Due to this the error path might release that slot twice or never,
depending on the error scenario.
xenvif_idx_release is also removed from xenvif_idx_unmap, and called separately.

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
---
v2: remove stray blank line

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 8cbf60d..6fff911 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1039,6 +1039,8 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
 	 */
 	struct skb_shared_info *first_shinfo = NULL;
 	int nr_frags = shinfo->nr_frags;
+	const bool sharedslot = nr_frags &&
+				frag_get_pending_idx(&shinfo->frags[0]) == pending_idx;
 	int i, err;
 
 	/* Check status of header. */
@@ -1051,7 +1053,10 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
 				   (*gopp_copy)->status,
 				   pending_idx,
 				   (*gopp_copy)->source.u.ref);
-		xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR);
+		/* The first frag might still have this slot mapped */
+		if (!sharedslot)
+			xenvif_idx_release(queue, pending_idx,
+					   XEN_NETIF_RSP_ERROR);
 	}
 
 check_frags:
@@ -1068,8 +1073,19 @@ check_frags:
 						pending_idx,
 						gop_map->handle);
 			/* Had a previous error? Invalidate this fragment. */
-			if (unlikely(err))
+			if (unlikely(err)) {
 				xenvif_idx_unmap(queue, pending_idx);
+				/* If the mapping of the first frag was OK, but
+				 * the header's copy failed, and they are
+				 * sharing a slot, send an error
+				 */
+				if (i == 0 && sharedslot)
+					xenvif_idx_release(queue, pending_idx,
+							   XEN_NETIF_RSP_ERROR);
+				else
+					xenvif_idx_release(queue, pending_idx,
+							   XEN_NETIF_RSP_OKAY);
+			}
 			continue;
 		}
 
@@ -1081,15 +1097,27 @@ check_frags:
 				   gop_map->status,
 				   pending_idx,
 				   gop_map->ref);
+
 		xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR);
 
 		/* Not the first error? Preceding frags already invalidated. */
 		if (err)
 			continue;
-		/* First error: invalidate preceding fragments. */
+
+		/* First error: if the header haven't shared a slot with the
+		 * first frag, release it as well.
+		 */
+		if (!sharedslot)
+			xenvif_idx_release(queue,
+					   XENVIF_TX_CB(skb)->pending_idx,
+					   XEN_NETIF_RSP_OKAY);
+
+		/* Invalidate preceding fragments of this skb. */
 		for (j = 0; j < i; j++) {
 			pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
 			xenvif_idx_unmap(queue, pending_idx);
+			xenvif_idx_release(queue, pending_idx,
+					   XEN_NETIF_RSP_OKAY);
 		}
 
 		/* And if we found the error while checking the frag_list, unmap
@@ -1099,6 +1127,8 @@ check_frags:
 			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);
+				xenvif_idx_release(queue, pending_idx,
+						   XEN_NETIF_RSP_OKAY);
 			}
 		}
 
@@ -1834,8 +1864,6 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx)
 			   tx_unmap_op.status);
 		BUG();
 	}
-
-	xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_OKAY);
 }
 
 static inline int rx_work_todo(struct xenvif_queue *queue)

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH net 4/4 v2] xen-netback: Fix pointer incrementation to avoid incorrect logging
  2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
                   ` (2 preceding siblings ...)
  2014-07-18 18:08 ` [PATCH net 3/4 v2] xen-netback: Fix releasing header slot on " Zoltan Kiss
@ 2014-07-18 18:08 ` Zoltan Kiss
  2014-07-21  3:57 ` [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-07-18 18:08 UTC (permalink / raw)
  To: Wei Liu, Ian Campbell; +Cc: Zoltan Kiss, netdev, linux-kernel, xen-devel

Due to this pointer is increased prematurely, the error log contains rubbish.

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
---
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index cca82de..72d8a6b 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1045,7 +1045,6 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
 
 	/* Check status of header. */
 	err = (*gopp_copy)->status;
-	(*gopp_copy)++;
 	if (unlikely(err)) {
 		if (net_ratelimit())
 			netdev_dbg(queue->vif->dev,
@@ -1058,6 +1057,7 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue,
 			xenvif_idx_release(queue, pending_idx,
 					   XEN_NETIF_RSP_ERROR);
 	}
+	(*gopp_copy)++;
 
 check_frags:
 	for (i = 0; i < nr_frags; i++, gop_map++) {

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop
  2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
                   ` (3 preceding siblings ...)
  2014-07-18 18:08 ` [PATCH net 4/4 v2] xen-netback: Fix pointer incrementation to avoid incorrect logging Zoltan Kiss
@ 2014-07-21  3:57 ` David Miller
  4 siblings, 0 replies; 6+ messages in thread
From: David Miller @ 2014-07-21  3:57 UTC (permalink / raw)
  To: zoltan.kiss; +Cc: wei.liu2, Ian.Campbell, netdev, linux-kernel, xen-devel

From: Zoltan Kiss <zoltan.kiss@citrix.com>
Date: Fri, 18 Jul 2014 19:08:01 +0100

> This series fixes a lot of bugs on the error path around this function, which
> were introduced with my grant mapping series in 3.15. They apply to the latest
> net tree, but probably to net-next as well without any modification.
> I'll post an another series which applies to 3.15 stable, as the problem was
> first discovered there. The only difference is that the "queue" variable name is
> replaced to "vif".
> 
> Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com>
> Reported-by: Armin Zentai <armin.zentai@ezit.hu>

Series applied, thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-07-21  3:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-18 18:08 [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop Zoltan Kiss
2014-07-18 18:08 ` [PATCH net 1/4 v2] xen-netback: Fix handling frag_list on grant op error path Zoltan Kiss
2014-07-18 18:08 ` [PATCH net 2/4 v2] xen-netback: Fix releasing frag_list skbs in " Zoltan Kiss
2014-07-18 18:08 ` [PATCH net 3/4 v2] xen-netback: Fix releasing header slot on " Zoltan Kiss
2014-07-18 18:08 ` [PATCH net 4/4 v2] xen-netback: Fix pointer incrementation to avoid incorrect logging Zoltan Kiss
2014-07-21  3:57 ` [PATCH net 0/4 v2] xen-netback: Fixing up xenvif_tx_check_gop David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).