All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
@ 2019-02-28  2:03 Igor Druzhinin
  2019-02-28  9:46 ` Paul Durrant
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Igor Druzhinin @ 2019-02-28  2:03 UTC (permalink / raw)
  To: xen-devel, netdev, linux-kernel
  Cc: wei.liu2, paul.durrant, davem, Igor Druzhinin

Zero-copy callback flag is not yet set on frag list skb at the moment
xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
leaking grant ref mappings since xenvif_zerocopy_callback() is never
called for these fragments. Those eventually build up and cause Xen
to kill Dom0 as the slots get reused for new mappings.

That behavior is observed under certain workloads where sudden spikes
of page cache usage for writes coexist with active atomic skb allocations.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
---
 drivers/net/xen-netback/netback.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a..2023317 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
 
 		if (unlikely(skb_has_frag_list(skb))) {
 			if (xenvif_handle_frag_list(queue, skb)) {
+				struct sk_buff *nskb =
+						skb_shinfo(skb)->frag_list;
 				if (net_ratelimit())
 					netdev_err(queue->vif->dev,
 						   "Not enough memory to consolidate frag_list!\n");
+				xenvif_skb_zerocopy_prepare(queue, nskb);
 				xenvif_skb_zerocopy_prepare(queue, skb);
 				kfree_skb(skb);
 				continue;
-- 
2.7.4


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

* RE: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  2:03 [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure Igor Druzhinin
@ 2019-02-28  9:46 ` Paul Durrant
  2019-02-28 11:01   ` Wei Liu
  2019-02-28 11:01   ` Wei Liu
  2019-02-28  9:46 ` Paul Durrant
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28  9:46 UTC (permalink / raw)
  To: Igor Druzhinin, xen-devel, netdev, linux-kernel
  Cc: Wei Liu, davem, Igor Druzhinin

> -----Original Message-----
> From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> Sent: 28 February 2019 02:03
> To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net; Igor
> Druzhinin <igor.druzhinin@citrix.com>
> Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> Zero-copy callback flag is not yet set on frag list skb at the moment
> xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> leaking grant ref mappings since xenvif_zerocopy_callback() is never
> called for these fragments. Those eventually build up and cause Xen
> to kill Dom0 as the slots get reused for new mappings.
> 
> That behavior is observed under certain workloads where sudden spikes
> of page cache usage for writes coexist with active atomic skb allocations.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> ---
>  drivers/net/xen-netback/netback.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a..2023317 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> 
>  		if (unlikely(skb_has_frag_list(skb))) {
>  			if (xenvif_handle_frag_list(queue, skb)) {
> +				struct sk_buff *nskb =
> +						skb_shinfo(skb)->frag_list;
>  				if (net_ratelimit())
>  					netdev_err(queue->vif->dev,
>  						   "Not enough memory to consolidate frag_list!\n");
> +				xenvif_skb_zerocopy_prepare(queue, nskb);
>  				xenvif_skb_zerocopy_prepare(queue, skb);
>  				kfree_skb(skb);
>  				continue;

Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two different places. Something like the following...

---8<---
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a32c2a..093c7b860772 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 /* Consolidate skb with a frag_list into a brand new one with local pages on
  * frags. Returns 0 or -ENOMEM if can't allocate new pages.
  */
-static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
+static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a32c2a..093c7b860772 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
eue,
 /* Consolidate skb with a frag_list into a brand new one with local pages on
  * frags. Returns 0 or -ENOMEM if can't allocate new pages.
  */
-static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
skb)
+static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
skb,
+                                  struct sk_buff *nskb)
 {
        unsigned int offset = skb_headlen(skb);
        skb_frag_t frags[MAX_SKB_FRAGS];
        int i, f;
        struct ubuf_info *uarg;
-       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;

        queue->stats.tx_zerocopy_sent += 2;
        queue->stats.tx_frag_overflow++;
@@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
ueue, struct sk_buff *s
                skb_frag_size_set(&frags[i], len);
        }

-       /* Copied all the bits from the frag list -- free it. */
-       skb_frag_list_init(skb);
-       xenvif_skb_zerocopy_prepare(queue, nskb);
-       kfree_skb(nskb);
-
        /* Release all the original (foreign) frags. */
        for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
                skb_frag_unref(skb, f);
@@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
                xenvif_fill_frags(queue, skb);

                if (unlikely(skb_has_frag_list(skb))) {
-                       if (xenvif_handle_frag_list(queue, skb)) {
+                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
+
+                       xenvif_skb_zerocopy_prepare(queue, nskb);
+
+                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
                                if (net_ratelimit())
                                        netdev_err(queue->vif->dev,
                                                   "Not enough memory to consolidate frag_list!\n");
@@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
                                kfree_skb(skb);
                                continue;
                        }
+
+                       /* Copied all the bits from the frag list. */
+                       skb_frag_list_init(skb);
+                       kfree(nskb);
                }

                skb->dev      = queue->vif->dev;
---8<---

What do you think?

  Paul

> --
> 2.7.4


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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  2:03 [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure Igor Druzhinin
  2019-02-28  9:46 ` Paul Durrant
@ 2019-02-28  9:46 ` Paul Durrant
  2019-02-28  9:50 ` Andrew Cooper
  2019-02-28  9:50 ` [Xen-devel] " Andrew Cooper
  3 siblings, 0 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28  9:46 UTC (permalink / raw)
  To: xen-devel, netdev, linux-kernel; +Cc: Igor Druzhinin, Wei Liu, davem

> -----Original Message-----
> From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> Sent: 28 February 2019 02:03
> To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net; Igor
> Druzhinin <igor.druzhinin@citrix.com>
> Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> Zero-copy callback flag is not yet set on frag list skb at the moment
> xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> leaking grant ref mappings since xenvif_zerocopy_callback() is never
> called for these fragments. Those eventually build up and cause Xen
> to kill Dom0 as the slots get reused for new mappings.
> 
> That behavior is observed under certain workloads where sudden spikes
> of page cache usage for writes coexist with active atomic skb allocations.
> 
> Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> ---
>  drivers/net/xen-netback/netback.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a..2023317 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> 
>  		if (unlikely(skb_has_frag_list(skb))) {
>  			if (xenvif_handle_frag_list(queue, skb)) {
> +				struct sk_buff *nskb =
> +						skb_shinfo(skb)->frag_list;
>  				if (net_ratelimit())
>  					netdev_err(queue->vif->dev,
>  						   "Not enough memory to consolidate frag_list!\n");
> +				xenvif_skb_zerocopy_prepare(queue, nskb);
>  				xenvif_skb_zerocopy_prepare(queue, skb);
>  				kfree_skb(skb);
>  				continue;

Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two different places. Something like the following...

---8<---
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a32c2a..093c7b860772 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 /* Consolidate skb with a frag_list into a brand new one with local pages on
  * frags. Returns 0 or -ENOMEM if can't allocate new pages.
  */
-static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
+static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a32c2a..093c7b860772 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
eue,
 /* Consolidate skb with a frag_list into a brand new one with local pages on
  * frags. Returns 0 or -ENOMEM if can't allocate new pages.
  */
-static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
skb)
+static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
skb,
+                                  struct sk_buff *nskb)
 {
        unsigned int offset = skb_headlen(skb);
        skb_frag_t frags[MAX_SKB_FRAGS];
        int i, f;
        struct ubuf_info *uarg;
-       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;

        queue->stats.tx_zerocopy_sent += 2;
        queue->stats.tx_frag_overflow++;
@@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
ueue, struct sk_buff *s
                skb_frag_size_set(&frags[i], len);
        }

-       /* Copied all the bits from the frag list -- free it. */
-       skb_frag_list_init(skb);
-       xenvif_skb_zerocopy_prepare(queue, nskb);
-       kfree_skb(nskb);
-
        /* Release all the original (foreign) frags. */
        for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
                skb_frag_unref(skb, f);
@@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
                xenvif_fill_frags(queue, skb);

                if (unlikely(skb_has_frag_list(skb))) {
-                       if (xenvif_handle_frag_list(queue, skb)) {
+                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
+
+                       xenvif_skb_zerocopy_prepare(queue, nskb);
+
+                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
                                if (net_ratelimit())
                                        netdev_err(queue->vif->dev,
                                                   "Not enough memory to consolidate frag_list!\n");
@@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
                                kfree_skb(skb);
                                continue;
                        }
+
+                       /* Copied all the bits from the frag list. */
+                       skb_frag_list_init(skb);
+                       kfree(nskb);
                }

                skb->dev      = queue->vif->dev;
---8<---

What do you think?

  Paul

> --
> 2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [Xen-devel] [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  2:03 [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure Igor Druzhinin
                   ` (2 preceding siblings ...)
  2019-02-28  9:50 ` Andrew Cooper
@ 2019-02-28  9:50 ` Andrew Cooper
  3 siblings, 0 replies; 18+ messages in thread
From: Andrew Cooper @ 2019-02-28  9:50 UTC (permalink / raw)
  To: Igor Druzhinin, xen-devel, netdev, linux-kernel
  Cc: paul.durrant, wei.liu2, davem

On 28/02/2019 02:03, Igor Druzhinin wrote:
> Zero-copy callback flag is not yet set on frag list skb at the moment
> xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> leaking grant ref mappings since xenvif_zerocopy_callback() is never
> called for these fragments. Those eventually build up and cause Xen
> to kill Dom0 as the slots get reused for new mappings.

Its worth pointing out what (debug) Xen notices is dom0 performing
implicit grant unmap.

~Andrew

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  2:03 [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure Igor Druzhinin
  2019-02-28  9:46 ` Paul Durrant
  2019-02-28  9:46 ` Paul Durrant
@ 2019-02-28  9:50 ` Andrew Cooper
  2019-02-28  9:50 ` [Xen-devel] " Andrew Cooper
  3 siblings, 0 replies; 18+ messages in thread
From: Andrew Cooper @ 2019-02-28  9:50 UTC (permalink / raw)
  To: Igor Druzhinin, xen-devel, netdev, linux-kernel
  Cc: paul.durrant, wei.liu2, davem

On 28/02/2019 02:03, Igor Druzhinin wrote:
> Zero-copy callback flag is not yet set on frag list skb at the moment
> xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> leaking grant ref mappings since xenvif_zerocopy_callback() is never
> called for these fragments. Those eventually build up and cause Xen
> to kill Dom0 as the slots get reused for new mappings.

Its worth pointing out what (debug) Xen notices is dom0 performing
implicit grant unmap.

~Andrew

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  9:46 ` Paul Durrant
@ 2019-02-28 11:01   ` Wei Liu
  2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:01   ` Wei Liu
  1 sibling, 2 replies; 18+ messages in thread
From: Wei Liu @ 2019-02-28 11:01 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Igor Druzhinin, xen-devel, netdev, linux-kernel, Wei Liu, davem

On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > Sent: 28 February 2019 02:03
> > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net; Igor
> > Druzhinin <igor.druzhinin@citrix.com>
> > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > 
> > Zero-copy callback flag is not yet set on frag list skb at the moment
> > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > called for these fragments. Those eventually build up and cause Xen
> > to kill Dom0 as the slots get reused for new mappings.
> > 
> > That behavior is observed under certain workloads where sudden spikes
> > of page cache usage for writes coexist with active atomic skb allocations.
> > 
> > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > ---
> >  drivers/net/xen-netback/netback.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a..2023317 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > 
> >  		if (unlikely(skb_has_frag_list(skb))) {
> >  			if (xenvif_handle_frag_list(queue, skb)) {
> > +				struct sk_buff *nskb =
> > +						skb_shinfo(skb)->frag_list;
> >  				if (net_ratelimit())
> >  					netdev_err(queue->vif->dev,
> >  						   "Not enough memory to consolidate frag_list!\n");
> > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> >  				xenvif_skb_zerocopy_prepare(queue, skb);
> >  				kfree_skb(skb);
> >  				continue;
> 
> Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two different places. Something like the following...

+1 for having only one place. 

> 
> ---8<---
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a32c2a..093c7b860772 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
>  /* Consolidate skb with a frag_list into a brand new one with local pages on
>   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
>   */
> -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a32c2a..093c7b860772 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> eue,
>  /* Consolidate skb with a frag_list into a brand new one with local pages on
>   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
>   */
> -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> skb)
> +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> skb,
> +                                  struct sk_buff *nskb)
>  {
>         unsigned int offset = skb_headlen(skb);
>         skb_frag_t frags[MAX_SKB_FRAGS];
>         int i, f;
>         struct ubuf_info *uarg;
> -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> 
>         queue->stats.tx_zerocopy_sent += 2;
>         queue->stats.tx_frag_overflow++;
> @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> ueue, struct sk_buff *s
>                 skb_frag_size_set(&frags[i], len);
>         }
> 
> -       /* Copied all the bits from the frag list -- free it. */
> -       skb_frag_list_init(skb);
> -       xenvif_skb_zerocopy_prepare(queue, nskb);
> -       kfree_skb(nskb);
> -
>         /* Release all the original (foreign) frags. */
>         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
>                 skb_frag_unref(skb, f);
> @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>                 xenvif_fill_frags(queue, skb);
> 
>                 if (unlikely(skb_has_frag_list(skb))) {
> -                       if (xenvif_handle_frag_list(queue, skb)) {
> +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> +
> +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> +
> +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
>                                 if (net_ratelimit())
>                                         netdev_err(queue->vif->dev,
>                                                    "Not enough memory to consolidate frag_list!\n");
> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>                                 kfree_skb(skb);
>                                 continue;
>                         }
> +
> +                       /* Copied all the bits from the frag list. */
> +                       skb_frag_list_init(skb);
> +                       kfree(nskb);

I think you want kfree_skb here?

Wei.

>                 }
> 
>                 skb->dev      = queue->vif->dev;
> ---8<---
> 
> What do you think?
> 
>   Paul
> 
> > --
> > 2.7.4
> 

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28  9:46 ` Paul Durrant
  2019-02-28 11:01   ` Wei Liu
@ 2019-02-28 11:01   ` Wei Liu
  1 sibling, 0 replies; 18+ messages in thread
From: Wei Liu @ 2019-02-28 11:01 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Igor Druzhinin, Wei Liu, netdev, linux-kernel, xen-devel, davem

On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > -----Original Message-----
> > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > Sent: 28 February 2019 02:03
> > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net; Igor
> > Druzhinin <igor.druzhinin@citrix.com>
> > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > 
> > Zero-copy callback flag is not yet set on frag list skb at the moment
> > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > called for these fragments. Those eventually build up and cause Xen
> > to kill Dom0 as the slots get reused for new mappings.
> > 
> > That behavior is observed under certain workloads where sudden spikes
> > of page cache usage for writes coexist with active atomic skb allocations.
> > 
> > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > ---
> >  drivers/net/xen-netback/netback.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a..2023317 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > 
> >  		if (unlikely(skb_has_frag_list(skb))) {
> >  			if (xenvif_handle_frag_list(queue, skb)) {
> > +				struct sk_buff *nskb =
> > +						skb_shinfo(skb)->frag_list;
> >  				if (net_ratelimit())
> >  					netdev_err(queue->vif->dev,
> >  						   "Not enough memory to consolidate frag_list!\n");
> > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> >  				xenvif_skb_zerocopy_prepare(queue, skb);
> >  				kfree_skb(skb);
> >  				continue;
> 
> Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two different places. Something like the following...

+1 for having only one place. 

> 
> ---8<---
> diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a32c2a..093c7b860772 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
>  /* Consolidate skb with a frag_list into a brand new one with local pages on
>   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
>   */
> -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> index 80aae3a32c2a..093c7b860772 100644
> --- a/drivers/net/xen-netback/netback.c
> +++ b/drivers/net/xen-netback/netback.c
> @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> eue,
>  /* Consolidate skb with a frag_list into a brand new one with local pages on
>   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
>   */
> -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> skb)
> +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> skb,
> +                                  struct sk_buff *nskb)
>  {
>         unsigned int offset = skb_headlen(skb);
>         skb_frag_t frags[MAX_SKB_FRAGS];
>         int i, f;
>         struct ubuf_info *uarg;
> -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> 
>         queue->stats.tx_zerocopy_sent += 2;
>         queue->stats.tx_frag_overflow++;
> @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> ueue, struct sk_buff *s
>                 skb_frag_size_set(&frags[i], len);
>         }
> 
> -       /* Copied all the bits from the frag list -- free it. */
> -       skb_frag_list_init(skb);
> -       xenvif_skb_zerocopy_prepare(queue, nskb);
> -       kfree_skb(nskb);
> -
>         /* Release all the original (foreign) frags. */
>         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
>                 skb_frag_unref(skb, f);
> @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>                 xenvif_fill_frags(queue, skb);
> 
>                 if (unlikely(skb_has_frag_list(skb))) {
> -                       if (xenvif_handle_frag_list(queue, skb)) {
> +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> +
> +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> +
> +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
>                                 if (net_ratelimit())
>                                         netdev_err(queue->vif->dev,
>                                                    "Not enough memory to consolidate frag_list!\n");
> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>                                 kfree_skb(skb);
>                                 continue;
>                         }
> +
> +                       /* Copied all the bits from the frag list. */
> +                       skb_frag_list_init(skb);
> +                       kfree(nskb);

I think you want kfree_skb here?

Wei.

>                 }
> 
>                 skb->dev      = queue->vif->dev;
> ---8<---
> 
> What do you think?
> 
>   Paul
> 
> > --
> > 2.7.4
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* RE: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:01   ` Wei Liu
  2019-02-28 11:21     ` Paul Durrant
@ 2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:43       ` Igor Druzhinin
                         ` (3 more replies)
  1 sibling, 4 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 11:21 UTC (permalink / raw)
  To: Wei Liu; +Cc: Igor Druzhinin, xen-devel, netdev, linux-kernel, Wei Liu, davem

> -----Original Message-----
> From: Wei Liu [mailto:wei.liu2@citrix.com]
> Sent: 28 February 2019 11:02
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; xen-devel@lists.xenproject.org;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Wei Liu <wei.liu2@citrix.com>;
> davem@davemloft.net
> Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > > Sent: 28 February 2019 02:03
> > > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net;
> Igor
> > > Druzhinin <igor.druzhinin@citrix.com>
> > > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > >
> > > Zero-copy callback flag is not yet set on frag list skb at the moment
> > > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > > called for these fragments. Those eventually build up and cause Xen
> > > to kill Dom0 as the slots get reused for new mappings.
> > >
> > > That behavior is observed under certain workloads where sudden spikes
> > > of page cache usage for writes coexist with active atomic skb allocations.
> > >
> > > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > > ---
> > >  drivers/net/xen-netback/netback.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a..2023317 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >
> > >  		if (unlikely(skb_has_frag_list(skb))) {
> > >  			if (xenvif_handle_frag_list(queue, skb)) {
> > > +				struct sk_buff *nskb =
> > > +						skb_shinfo(skb)->frag_list;
> > >  				if (net_ratelimit())
> > >  					netdev_err(queue->vif->dev,
> > >  						   "Not enough memory to consolidate frag_list!\n");
> > > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> > >  				xenvif_skb_zerocopy_prepare(queue, skb);
> > >  				kfree_skb(skb);
> > >  				continue;
> >
> > Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from
> inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two
> different places. Something like the following...
> 
> +1 for having only one place.
> 
> >
> > ---8<---
> > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a32c2a..093c7b860772 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
> >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> >   */
> > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git
> a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a32c2a..093c7b860772 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> > eue,
> >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> >   */
> > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > skb)
> > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > skb,
> > +                                  struct sk_buff *nskb)
> >  {
> >         unsigned int offset = skb_headlen(skb);
> >         skb_frag_t frags[MAX_SKB_FRAGS];
> >         int i, f;
> >         struct ubuf_info *uarg;
> > -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> >
> >         queue->stats.tx_zerocopy_sent += 2;
> >         queue->stats.tx_frag_overflow++;
> > @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> > ueue, struct sk_buff *s
> >                 skb_frag_size_set(&frags[i], len);
> >         }
> >
> > -       /* Copied all the bits from the frag list -- free it. */
> > -       skb_frag_list_init(skb);
> > -       xenvif_skb_zerocopy_prepare(queue, nskb);
> > -       kfree_skb(nskb);
> > -
> >         /* Release all the original (foreign) frags. */
> >         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
> >                 skb_frag_unref(skb, f);
> > @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >                 xenvif_fill_frags(queue, skb);
> >
> >                 if (unlikely(skb_has_frag_list(skb))) {
> > -                       if (xenvif_handle_frag_list(queue, skb)) {
> > +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > +
> > +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> > +
> > +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
> >                                 if (net_ratelimit())
> >                                         netdev_err(queue->vif->dev,
> >                                                    "Not enough memory to consolidate frag_list!\n");
> > @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >                                 kfree_skb(skb);
> >                                 continue;
> >                         }
> > +
> > +                       /* Copied all the bits from the frag list. */
> > +                       skb_frag_list_init(skb);
> > +                       kfree(nskb);
> 
> I think you want kfree_skb here?

No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it can be freed on its own. The skb is what we need to retain, because that now contains all the data.

  Cheers,

    Paul

> 
> Wei.
> 
> >                 }
> >
> >                 skb->dev      = queue->vif->dev;
> > ---8<---
> >
> > What do you think?
> >
> >   Paul
> >
> > > --
> > > 2.7.4
> >

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:01   ` Wei Liu
@ 2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:21     ` Paul Durrant
  1 sibling, 0 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 11:21 UTC (permalink / raw)
  Cc: Igor Druzhinin, Wei Liu, netdev, linux-kernel, xen-devel, davem

> -----Original Message-----
> From: Wei Liu [mailto:wei.liu2@citrix.com]
> Sent: 28 February 2019 11:02
> To: Paul Durrant <Paul.Durrant@citrix.com>
> Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; xen-devel@lists.xenproject.org;
> netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Wei Liu <wei.liu2@citrix.com>;
> davem@davemloft.net
> Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > > -----Original Message-----
> > > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > > Sent: 28 February 2019 02:03
> > > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net;
> Igor
> > > Druzhinin <igor.druzhinin@citrix.com>
> > > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > >
> > > Zero-copy callback flag is not yet set on frag list skb at the moment
> > > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > > called for these fragments. Those eventually build up and cause Xen
> > > to kill Dom0 as the slots get reused for new mappings.
> > >
> > > That behavior is observed under certain workloads where sudden spikes
> > > of page cache usage for writes coexist with active atomic skb allocations.
> > >
> > > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > > ---
> > >  drivers/net/xen-netback/netback.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a..2023317 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >
> > >  		if (unlikely(skb_has_frag_list(skb))) {
> > >  			if (xenvif_handle_frag_list(queue, skb)) {
> > > +				struct sk_buff *nskb =
> > > +						skb_shinfo(skb)->frag_list;
> > >  				if (net_ratelimit())
> > >  					netdev_err(queue->vif->dev,
> > >  						   "Not enough memory to consolidate frag_list!\n");
> > > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> > >  				xenvif_skb_zerocopy_prepare(queue, skb);
> > >  				kfree_skb(skb);
> > >  				continue;
> >
> > Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from
> inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two
> different places. Something like the following...
> 
> +1 for having only one place.
> 
> >
> > ---8<---
> > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a32c2a..093c7b860772 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
> >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> >   */
> > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git
> a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > index 80aae3a32c2a..093c7b860772 100644
> > --- a/drivers/net/xen-netback/netback.c
> > +++ b/drivers/net/xen-netback/netback.c
> > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> > eue,
> >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> >   */
> > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > skb)
> > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > skb,
> > +                                  struct sk_buff *nskb)
> >  {
> >         unsigned int offset = skb_headlen(skb);
> >         skb_frag_t frags[MAX_SKB_FRAGS];
> >         int i, f;
> >         struct ubuf_info *uarg;
> > -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> >
> >         queue->stats.tx_zerocopy_sent += 2;
> >         queue->stats.tx_frag_overflow++;
> > @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> > ueue, struct sk_buff *s
> >                 skb_frag_size_set(&frags[i], len);
> >         }
> >
> > -       /* Copied all the bits from the frag list -- free it. */
> > -       skb_frag_list_init(skb);
> > -       xenvif_skb_zerocopy_prepare(queue, nskb);
> > -       kfree_skb(nskb);
> > -
> >         /* Release all the original (foreign) frags. */
> >         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
> >                 skb_frag_unref(skb, f);
> > @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >                 xenvif_fill_frags(queue, skb);
> >
> >                 if (unlikely(skb_has_frag_list(skb))) {
> > -                       if (xenvif_handle_frag_list(queue, skb)) {
> > +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > +
> > +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> > +
> > +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
> >                                 if (net_ratelimit())
> >                                         netdev_err(queue->vif->dev,
> >                                                    "Not enough memory to consolidate frag_list!\n");
> > @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >                                 kfree_skb(skb);
> >                                 continue;
> >                         }
> > +
> > +                       /* Copied all the bits from the frag list. */
> > +                       skb_frag_list_init(skb);
> > +                       kfree(nskb);
> 
> I think you want kfree_skb here?

No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it can be freed on its own. The skb is what we need to retain, because that now contains all the data.

  Cheers,

    Paul

> 
> Wei.
> 
> >                 }
> >
> >                 skb->dev      = queue->vif->dev;
> > ---8<---
> >
> > What do you think?
> >
> >   Paul
> >
> > > --
> > > 2.7.4
> >

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:43       ` Igor Druzhinin
@ 2019-02-28 11:43       ` Igor Druzhinin
  2019-02-28 11:49         ` Paul Durrant
  2019-02-28 11:49         ` Paul Durrant
  2019-02-28 12:07       ` Paul Durrant
  2019-02-28 12:07       ` Paul Durrant
  3 siblings, 2 replies; 18+ messages in thread
From: Igor Druzhinin @ 2019-02-28 11:43 UTC (permalink / raw)
  To: Paul Durrant, Wei Liu; +Cc: xen-devel, netdev, linux-kernel, davem

On 28/02/2019 11:21, Paul Durrant wrote:
>>> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>>>                                 kfree_skb(skb);
>>>                                 continue;
>>>                         }
>>> +
>>> +                       /* Copied all the bits from the frag list. */
>>> +                       skb_frag_list_init(skb);
>>> +                       kfree(nskb);
>>
>> I think you want kfree_skb here?
> 
> No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it can be freed on its own. The skb is what we need to retain, because that now contains all the data.
> 

Are you saying previous code in xenvif_handle_frag_list() incorrectly
called kfree_skb()?

Igor

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:21     ` Paul Durrant
@ 2019-02-28 11:43       ` Igor Druzhinin
  2019-02-28 11:43       ` Igor Druzhinin
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 18+ messages in thread
From: Igor Druzhinin @ 2019-02-28 11:43 UTC (permalink / raw)
  To: Paul Durrant, Wei Liu; +Cc: xen-devel, davem, linux-kernel, netdev

On 28/02/2019 11:21, Paul Durrant wrote:
>>> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
>>>                                 kfree_skb(skb);
>>>                                 continue;
>>>                         }
>>> +
>>> +                       /* Copied all the bits from the frag list. */
>>> +                       skb_frag_list_init(skb);
>>> +                       kfree(nskb);
>>
>> I think you want kfree_skb here?
> 
> No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it can be freed on its own. The skb is what we need to retain, because that now contains all the data.
> 

Are you saying previous code in xenvif_handle_frag_list() incorrectly
called kfree_skb()?

Igor

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* RE: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:43       ` Igor Druzhinin
@ 2019-02-28 11:49         ` Paul Durrant
  2019-02-28 11:49         ` Paul Durrant
  1 sibling, 0 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 11:49 UTC (permalink / raw)
  To: Igor Druzhinin, Wei Liu; +Cc: xen-devel, netdev, linux-kernel, davem

> -----Original Message-----
> From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> Sent: 28 February 2019 11:44
> To: Paul Durrant <Paul.Durrant@citrix.com>; Wei Liu <wei.liu2@citrix.com>
> Cc: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> davem@davemloft.net
> Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> On 28/02/2019 11:21, Paul Durrant wrote:
> >>> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >>>                                 kfree_skb(skb);
> >>>                                 continue;
> >>>                         }
> >>> +
> >>> +                       /* Copied all the bits from the frag list. */
> >>> +                       skb_frag_list_init(skb);
> >>> +                       kfree(nskb);
> >>
> >> I think you want kfree_skb here?
> >
> > No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it
> can be freed on its own. The skb is what we need to retain, because that now contains all the data.
> >
> 
> Are you saying previous code in xenvif_handle_frag_list() incorrectly
> called kfree_skb()?

No, it correctly called kfree_skb() on nskb in the success case. What Wei and myself would prefer is that we have a single place that the frag list is freed in both the success and error cases.

  Paul

> 
> Igor

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:43       ` Igor Druzhinin
  2019-02-28 11:49         ` Paul Durrant
@ 2019-02-28 11:49         ` Paul Durrant
  1 sibling, 0 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 11:49 UTC (permalink / raw)
  To: Igor Druzhinin, Wei Liu; +Cc: xen-devel, davem, linux-kernel, netdev

> -----Original Message-----
> From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> Sent: 28 February 2019 11:44
> To: Paul Durrant <Paul.Durrant@citrix.com>; Wei Liu <wei.liu2@citrix.com>
> Cc: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org;
> davem@davemloft.net
> Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> 
> On 28/02/2019 11:21, Paul Durrant wrote:
> >>> @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> >>>                                 kfree_skb(skb);
> >>>                                 continue;
> >>>                         }
> >>> +
> >>> +                       /* Copied all the bits from the frag list. */
> >>> +                       skb_frag_list_init(skb);
> >>> +                       kfree(nskb);
> >>
> >> I think you want kfree_skb here?
> >
> > No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it
> can be freed on its own. The skb is what we need to retain, because that now contains all the data.
> >
> 
> Are you saying previous code in xenvif_handle_frag_list() incorrectly
> called kfree_skb()?

No, it correctly called kfree_skb() on nskb in the success case. What Wei and myself would prefer is that we have a single place that the frag list is freed in both the success and error cases.

  Paul

> 
> Igor
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* RE: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:21     ` Paul Durrant
  2019-02-28 11:43       ` Igor Druzhinin
  2019-02-28 11:43       ` Igor Druzhinin
@ 2019-02-28 12:07       ` Paul Durrant
  2019-02-28 12:37         ` Wei Liu
  2019-02-28 12:37         ` Wei Liu
  2019-02-28 12:07       ` Paul Durrant
  3 siblings, 2 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 12:07 UTC (permalink / raw)
  To: Paul Durrant, Wei Liu
  Cc: Igor Druzhinin, Wei Liu, netdev, linux-kernel, xen-devel, davem



> -----Original Message-----
> From: Xen-devel [mailto:xen-devel-bounces@lists.xenproject.org] On Behalf Of Paul Durrant
> Sent: 28 February 2019 11:22
> To: Wei Liu <wei.liu2@citrix.com>
> Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; Wei Liu <wei.liu2@citrix.com>; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org; xen-devel@lists.xenproject.org; davem@davemloft.net
> Subject: Re: [Xen-devel] [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory
> pressure
> 
> > -----Original Message-----
> > From: Wei Liu [mailto:wei.liu2@citrix.com]
> > Sent: 28 February 2019 11:02
> > To: Paul Durrant <Paul.Durrant@citrix.com>
> > Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; xen-devel@lists.xenproject.org;
> > netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Wei Liu <wei.liu2@citrix.com>;
> > davem@davemloft.net
> > Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> >
> > On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > > > -----Original Message-----
> > > > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > > > Sent: 28 February 2019 02:03
> > > > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > > > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net;
> > Igor
> > > > Druzhinin <igor.druzhinin@citrix.com>
> > > > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > > >
> > > > Zero-copy callback flag is not yet set on frag list skb at the moment
> > > > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > > > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > > > called for these fragments. Those eventually build up and cause Xen
> > > > to kill Dom0 as the slots get reused for new mappings.
> > > >
> > > > That behavior is observed under certain workloads where sudden spikes
> > > > of page cache usage for writes coexist with active atomic skb allocations.
> > > >
> > > > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > > > ---
> > > >  drivers/net/xen-netback/netback.c | 3 +++
> > > >  1 file changed, 3 insertions(+)
> > > >
> > > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > > index 80aae3a..2023317 100644
> > > > --- a/drivers/net/xen-netback/netback.c
> > > > +++ b/drivers/net/xen-netback/netback.c
> > > > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > > >
> > > >  		if (unlikely(skb_has_frag_list(skb))) {
> > > >  			if (xenvif_handle_frag_list(queue, skb)) {
> > > > +				struct sk_buff *nskb =
> > > > +						skb_shinfo(skb)->frag_list;
> > > >  				if (net_ratelimit())
> > > >  					netdev_err(queue->vif->dev,
> > > >  						   "Not enough memory to consolidate frag_list!\n");
> > > > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> > > >  				xenvif_skb_zerocopy_prepare(queue, skb);
> > > >  				kfree_skb(skb);
> > > >  				continue;
> > >
> > > Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from
> > inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two
> > different places. Something like the following...
> >
> > +1 for having only one place.
> >
> > >
> > > ---8<---
> > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a32c2a..093c7b860772 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
> > >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> > >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> > >   */
> > > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> > > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git
> > a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a32c2a..093c7b860772 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> > > eue,
> > >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> > >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> > >   */
> > > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > > skb)
> > > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > > skb,
> > > +                                  struct sk_buff *nskb)
> > >  {
> > >         unsigned int offset = skb_headlen(skb);
> > >         skb_frag_t frags[MAX_SKB_FRAGS];
> > >         int i, f;
> > >         struct ubuf_info *uarg;
> > > -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > >
> > >         queue->stats.tx_zerocopy_sent += 2;
> > >         queue->stats.tx_frag_overflow++;
> > > @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> > > ueue, struct sk_buff *s
> > >                 skb_frag_size_set(&frags[i], len);
> > >         }
> > >
> > > -       /* Copied all the bits from the frag list -- free it. */
> > > -       skb_frag_list_init(skb);
> > > -       xenvif_skb_zerocopy_prepare(queue, nskb);
> > > -       kfree_skb(nskb);
> > > -
> > >         /* Release all the original (foreign) frags. */
> > >         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
> > >                 skb_frag_unref(skb, f);
> > > @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >                 xenvif_fill_frags(queue, skb);
> > >
> > >                 if (unlikely(skb_has_frag_list(skb))) {
> > > -                       if (xenvif_handle_frag_list(queue, skb)) {
> > > +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > > +
> > > +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> > > +
> > > +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
> > >                                 if (net_ratelimit())
> > >                                         netdev_err(queue->vif->dev,
> > >                                                    "Not enough memory to consolidate
> frag_list!\n");
> > > @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >                                 kfree_skb(skb);
> > >                                 continue;
> > >                         }
> > > +
> > > +                       /* Copied all the bits from the frag list. */
> > > +                       skb_frag_list_init(skb);
> > > +                       kfree(nskb);
> >
> > I think you want kfree_skb here?
> 
> No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it
> can be freed on its own. The skb is what we need to retain, because that now contains all the data.

Sorry I misread/understood what you were getting at. Yes, I meant kfree_skb(nskb).

  Paul

> 
>   Cheers,
> 
>     Paul
> 
> >
> > Wei.
> >
> > >                 }
> > >
> > >                 skb->dev      = queue->vif->dev;
> > > ---8<---
> > >
> > > What do you think?
> > >
> > >   Paul
> > >
> > > > --
> > > > 2.7.4
> > >
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xenproject.org
> https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 11:21     ` Paul Durrant
                         ` (2 preceding siblings ...)
  2019-02-28 12:07       ` Paul Durrant
@ 2019-02-28 12:07       ` Paul Durrant
  3 siblings, 0 replies; 18+ messages in thread
From: Paul Durrant @ 2019-02-28 12:07 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Igor Druzhinin, Wei Liu, netdev, linux-kernel, xen-devel, davem



> -----Original Message-----
> From: Xen-devel [mailto:xen-devel-bounces@lists.xenproject.org] On Behalf Of Paul Durrant
> Sent: 28 February 2019 11:22
> To: Wei Liu <wei.liu2@citrix.com>
> Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; Wei Liu <wei.liu2@citrix.com>; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org; xen-devel@lists.xenproject.org; davem@davemloft.net
> Subject: Re: [Xen-devel] [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory
> pressure
> 
> > -----Original Message-----
> > From: Wei Liu [mailto:wei.liu2@citrix.com]
> > Sent: 28 February 2019 11:02
> > To: Paul Durrant <Paul.Durrant@citrix.com>
> > Cc: Igor Druzhinin <igor.druzhinin@citrix.com>; xen-devel@lists.xenproject.org;
> > netdev@vger.kernel.org; linux-kernel@vger.kernel.org; Wei Liu <wei.liu2@citrix.com>;
> > davem@davemloft.net
> > Subject: Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> >
> > On Thu, Feb 28, 2019 at 09:46:57AM +0000, Paul Durrant wrote:
> > > > -----Original Message-----
> > > > From: Igor Druzhinin [mailto:igor.druzhinin@citrix.com]
> > > > Sent: 28 February 2019 02:03
> > > > To: xen-devel@lists.xenproject.org; netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> > > > Cc: Wei Liu <wei.liu2@citrix.com>; Paul Durrant <Paul.Durrant@citrix.com>; davem@davemloft.net;
> > Igor
> > > > Druzhinin <igor.druzhinin@citrix.com>
> > > > Subject: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
> > > >
> > > > Zero-copy callback flag is not yet set on frag list skb at the moment
> > > > xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
> > > > leaking grant ref mappings since xenvif_zerocopy_callback() is never
> > > > called for these fragments. Those eventually build up and cause Xen
> > > > to kill Dom0 as the slots get reused for new mappings.
> > > >
> > > > That behavior is observed under certain workloads where sudden spikes
> > > > of page cache usage for writes coexist with active atomic skb allocations.
> > > >
> > > > Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
> > > > ---
> > > >  drivers/net/xen-netback/netback.c | 3 +++
> > > >  1 file changed, 3 insertions(+)
> > > >
> > > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > > index 80aae3a..2023317 100644
> > > > --- a/drivers/net/xen-netback/netback.c
> > > > +++ b/drivers/net/xen-netback/netback.c
> > > > @@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > > >
> > > >  		if (unlikely(skb_has_frag_list(skb))) {
> > > >  			if (xenvif_handle_frag_list(queue, skb)) {
> > > > +				struct sk_buff *nskb =
> > > > +						skb_shinfo(skb)->frag_list;
> > > >  				if (net_ratelimit())
> > > >  					netdev_err(queue->vif->dev,
> > > >  						   "Not enough memory to consolidate frag_list!\n");
> > > > +				xenvif_skb_zerocopy_prepare(queue, nskb);
> > > >  				xenvif_skb_zerocopy_prepare(queue, skb);
> > > >  				kfree_skb(skb);
> > > >  				continue;
> > >
> > > Whilst this fix will do the job, I think it would be better to get rid of the kfree_skb() from
> > inside xenvif_handle_frag_list() and always deal with it here rather than having it happen in two
> > different places. Something like the following...
> >
> > +1 for having only one place.
> >
> > >
> > > ---8<---
> > > diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a32c2a..093c7b860772 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
> > >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> > >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> > >   */
> > > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *skb)
> > > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *diff --git
> > a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
> > > index 80aae3a32c2a..093c7b860772 100644
> > > --- a/drivers/net/xen-netback/netback.c
> > > +++ b/drivers/net/xen-netback/netback.c
> > > @@ -1027,13 +1027,13 @@ static void xenvif_tx_build_gops(struct xenvif_queue *qu
> > > eue,
> > >  /* Consolidate skb with a frag_list into a brand new one with local pages on
> > >   * frags. Returns 0 or -ENOMEM if can't allocate new pages.
> > >   */
> > > -static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > > skb)
> > > +static int xenvif_handle_frag_list(struct xenvif_queue *queue, struct sk_buff *
> > > skb,
> > > +                                  struct sk_buff *nskb)
> > >  {
> > >         unsigned int offset = skb_headlen(skb);
> > >         skb_frag_t frags[MAX_SKB_FRAGS];
> > >         int i, f;
> > >         struct ubuf_info *uarg;
> > > -       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > >
> > >         queue->stats.tx_zerocopy_sent += 2;
> > >         queue->stats.tx_frag_overflow++;
> > > @@ -1072,11 +1072,6 @@ static int xenvif_handle_frag_list(struct xenvif_queue *q
> > > ueue, struct sk_buff *s
> > >                 skb_frag_size_set(&frags[i], len);
> > >         }
> > >
> > > -       /* Copied all the bits from the frag list -- free it. */
> > > -       skb_frag_list_init(skb);
> > > -       xenvif_skb_zerocopy_prepare(queue, nskb);
> > > -       kfree_skb(nskb);
> > > -
> > >         /* Release all the original (foreign) frags. */
> > >         for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
> > >                 skb_frag_unref(skb, f);
> > > @@ -1145,7 +1140,11 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >                 xenvif_fill_frags(queue, skb);
> > >
> > >                 if (unlikely(skb_has_frag_list(skb))) {
> > > -                       if (xenvif_handle_frag_list(queue, skb)) {
> > > +                       struct sk_buff *nskb = skb_shinfo(skb)->frag_list;
> > > +
> > > +                       xenvif_skb_zerocopy_prepare(queue, nskb);
> > > +
> > > +                       if (xenvif_handle_frag_list(queue, skb, nskb)) {
> > >                                 if (net_ratelimit())
> > >                                         netdev_err(queue->vif->dev,
> > >                                                    "Not enough memory to consolidate
> frag_list!\n");
> > > @@ -1153,6 +1152,10 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
> > >                                 kfree_skb(skb);
> > >                                 continue;
> > >                         }
> > > +
> > > +                       /* Copied all the bits from the frag list. */
> > > +                       skb_frag_list_init(skb);
> > > +                       kfree(nskb);
> >
> > I think you want kfree_skb here?
> 
> No. nskb is the frag list... it is unlinked from skb by the call to skb_frag_list_init() and then it
> can be freed on its own. The skb is what we need to retain, because that now contains all the data.

Sorry I misread/understood what you were getting at. Yes, I meant kfree_skb(nskb).

  Paul

> 
>   Cheers,
> 
>     Paul
> 
> >
> > Wei.
> >
> > >                 }
> > >
> > >                 skb->dev      = queue->vif->dev;
> > > ---8<---
> > >
> > > What do you think?
> > >
> > >   Paul
> > >
> > > > --
> > > > 2.7.4
> > >
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xenproject.org
> https://lists.xenproject.org/mailman/listinfo/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 12:07       ` Paul Durrant
  2019-02-28 12:37         ` Wei Liu
@ 2019-02-28 12:37         ` Wei Liu
  1 sibling, 0 replies; 18+ messages in thread
From: Wei Liu @ 2019-02-28 12:37 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Wei Liu, Igor Druzhinin, netdev, linux-kernel, xen-devel, davem

On Thu, Feb 28, 2019 at 12:07:07PM +0000, Paul Durrant wrote:
> Yes, I meant kfree_skb(nskb).
> 

In that case I think your patch looks fine.

Wei.

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

* Re: [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
  2019-02-28 12:07       ` Paul Durrant
@ 2019-02-28 12:37         ` Wei Liu
  2019-02-28 12:37         ` Wei Liu
  1 sibling, 0 replies; 18+ messages in thread
From: Wei Liu @ 2019-02-28 12:37 UTC (permalink / raw)
  To: Paul Durrant
  Cc: Igor Druzhinin, Wei Liu, netdev, linux-kernel, xen-devel, davem

On Thu, Feb 28, 2019 at 12:07:07PM +0000, Paul Durrant wrote:
> Yes, I meant kfree_skb(nskb).
> 

In that case I think your patch looks fine.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

* [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure
@ 2019-02-28  2:03 Igor Druzhinin
  0 siblings, 0 replies; 18+ messages in thread
From: Igor Druzhinin @ 2019-02-28  2:03 UTC (permalink / raw)
  To: xen-devel, netdev, linux-kernel
  Cc: Igor Druzhinin, paul.durrant, wei.liu2, davem

Zero-copy callback flag is not yet set on frag list skb at the moment
xenvif_handle_frag_list() returns -ENOMEM. This eventually results in
leaking grant ref mappings since xenvif_zerocopy_callback() is never
called for these fragments. Those eventually build up and cause Xen
to kill Dom0 as the slots get reused for new mappings.

That behavior is observed under certain workloads where sudden spikes
of page cache usage for writes coexist with active atomic skb allocations.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
---
 drivers/net/xen-netback/netback.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 80aae3a..2023317 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -1146,9 +1146,12 @@ static int xenvif_tx_submit(struct xenvif_queue *queue)
 
 		if (unlikely(skb_has_frag_list(skb))) {
 			if (xenvif_handle_frag_list(queue, skb)) {
+				struct sk_buff *nskb =
+						skb_shinfo(skb)->frag_list;
 				if (net_ratelimit())
 					netdev_err(queue->vif->dev,
 						   "Not enough memory to consolidate frag_list!\n");
+				xenvif_skb_zerocopy_prepare(queue, nskb);
 				xenvif_skb_zerocopy_prepare(queue, skb);
 				kfree_skb(skb);
 				continue;
-- 
2.7.4


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

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

end of thread, other threads:[~2019-02-28 12:37 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-28  2:03 [PATCH] xen-netback: fix occasional leak of grant ref mappings under memory pressure Igor Druzhinin
2019-02-28  9:46 ` Paul Durrant
2019-02-28 11:01   ` Wei Liu
2019-02-28 11:21     ` Paul Durrant
2019-02-28 11:21     ` Paul Durrant
2019-02-28 11:43       ` Igor Druzhinin
2019-02-28 11:43       ` Igor Druzhinin
2019-02-28 11:49         ` Paul Durrant
2019-02-28 11:49         ` Paul Durrant
2019-02-28 12:07       ` Paul Durrant
2019-02-28 12:37         ` Wei Liu
2019-02-28 12:37         ` Wei Liu
2019-02-28 12:07       ` Paul Durrant
2019-02-28 11:01   ` Wei Liu
2019-02-28  9:46 ` Paul Durrant
2019-02-28  9:50 ` Andrew Cooper
2019-02-28  9:50 ` [Xen-devel] " Andrew Cooper
  -- strict thread matches above, loose matches on Subject: below --
2019-02-28  2:03 Igor Druzhinin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.