All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jarek Poplawski <jarkao2@gmail.com>
To: David Miller <davem@davemloft.net>
Cc: eric.dumazet@gmail.com, netdev@vger.kernel.org
Subject: Re: [PATCH net-next-2.6] net: pskb_expand_head() optimization
Date: Sat, 11 Sep 2010 14:31:40 +0200	[thread overview]
Message-ID: <20100911123140.GA1939@del.dom.local> (raw)
In-Reply-To: <20100910.125449.235704956.davem@davemloft.net>

On Fri, Sep 10, 2010 at 12:54:49PM -0700, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 07 Sep 2010 11:37:28 +0200
> 
> > Le mardi 07 septembre 2010 ? 09:16 +0000, Jarek Poplawski a écrit :
> >> On 2010-09-07 07:02, Eric Dumazet wrote:
> > 
> >> > 
> >> > I understand what you want to do, but problem is we need to perform a
> >> > CAS2 operation : atomically changes two values (dataref and frag_list)
> >> 
> >> Alas I can't understand why do you think these clone and atomic tests
> >> in skb_release_data() don't protect skb_shinfo(skb)->frag_list enough.
> >> 
> > 
> > It was early in the morning, before a cup of tea.
> > 
> > David only had to set frag_list in the new shinfo, not the old.
> 
> Ok, how does this look?
> 
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index 752c197..aaa9750 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -327,6 +327,32 @@ static void skb_clone_fraglist(struct sk_buff *skb)
>  		skb_get(list);
>  }
>  
> +static struct sk_buff *skb_copy_fraglist(struct sk_buff *parent,
> +					 gfp_t gfp_mask)
> +{
> +	struct sk_buff *first_skb = NULL;
> +	struct sk_buff *prev_skb = NULL;
> +	struct sk_buff *skb;
> +
> +	skb_walk_frags(parent, skb) {
> +		struct sk_buff *nskb = pskb_copy(skb, gfp_mask);
> +
> +		if (!nskb)
> +			goto fail;
> +		if (!first_skb)
> +			first_skb = skb;

Probably here and below: "= nskb"

> +		else
> +			prev_skb->next = skb;
> +		prev_skb = skb;
> +	}
> +
> +	return first_skb;
> +
> +fail:

With "if (first_skb)" here it would look better to me even if it
currently doesn't matter.

Otherwise seems OK, but I still would like to know the scenario
demanding this change.

Jarek P.

> +	skb_drop_list(&first_skb);
> +	return NULL;
> +}
> +
>  static void skb_release_data(struct sk_buff *skb)
>  {
>  	if (!skb->cloned ||
> @@ -775,11 +801,12 @@ EXPORT_SYMBOL(pskb_copy);
>  int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
>  		     gfp_t gfp_mask)
>  {
> -	int i;
> -	u8 *data;
>  	int size = nhead + (skb_end_pointer(skb) - skb->head) + ntail;
> -	long off;
> +	struct skb_shared_info *new_shinfo;
>  	bool fastpath;
> +	u8 *data;
> +	long off;
> +	int i;
>  
>  	BUG_ON(nhead < 0);
>  
> @@ -797,8 +824,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
>  	 */
>  	memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head);
>  
> -	memcpy((struct skb_shared_info *)(data + size),
> -	       skb_shinfo(skb),
> +	new_shinfo = (struct skb_shared_info *)(data + size);
> +	memcpy(new_shinfo, skb_shinfo(skb),
>  	       offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags]));
>  
>  	/* Check if we can avoid taking references on fragments if we own
> @@ -815,14 +842,20 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
>  	if (fastpath) {
>  		kfree(skb->head);
>  	} else {
> +		if (skb_has_frag_list(skb)) {
> +			struct sk_buff *new_list;
> +
> +			new_list = skb_copy_fraglist(skb, gfp_mask);
> +			if (!new_list)
> +				goto free_data;
> +			new_shinfo->frag_list = new_list;
> +		}
>  		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
>  			get_page(skb_shinfo(skb)->frags[i].page);
>  
> -		if (skb_has_frag_list(skb))
> -			skb_clone_fraglist(skb);
> -
>  		skb_release_data(skb);
>  	}
> +
>  	off = (data + nhead) - skb->head;
>  
>  	skb->head     = data;
> @@ -848,6 +881,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
>  	atomic_set(&skb_shinfo(skb)->dataref, 1);
>  	return 0;
>  
> +free_data:
> +	kfree(data);
>  nodata:
>  	return -ENOMEM;
>  }

  reply	other threads:[~2010-09-11 12:32 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-03  3:43 [PATCH] net: Frag list lost on head expansion David Miller
2010-09-03  5:48 ` Eric Dumazet
2010-09-03  6:19   ` Eric Dumazet
2010-09-03  9:09   ` [PATCH net-next-2.6] net: pskb_expand_head() optimization Eric Dumazet
2010-09-03 13:46     ` David Miller
2010-09-07  2:20       ` David Miller
2010-09-07  5:02         ` Eric Dumazet
2010-09-07  5:05           ` David Miller
2010-09-07  9:16           ` Jarek Poplawski
2010-09-07  9:37             ` Eric Dumazet
2010-09-10 19:54               ` David Miller
2010-09-11 12:31                 ` Jarek Poplawski [this message]
2010-09-12  3:30                   ` David Miller
2010-09-12 10:45                     ` Jarek Poplawski
2010-09-12 10:58                       ` Jarek Poplawski
2010-09-12 15:58                       ` David Miller
2010-09-12 16:13                         ` David Miller
2010-09-12 20:57                           ` Jarek Poplawski
2010-09-12 22:08                             ` David Miller
2010-09-13  7:49                               ` Jarek Poplawski
2010-09-12 19:55                         ` Ben Pfaff
2010-09-12 20:24                           ` David Miller
2010-09-12 20:45                         ` Jarek Poplawski
2010-09-20  0:17                   ` David Miller
2010-09-20  7:21                     ` Jarek Poplawski
2010-09-20  9:02                       ` Eric Dumazet
2010-09-20  9:14                         ` Jarek Poplawski
2010-09-20 12:12                           ` Jarek Poplawski
2010-09-20 12:40                             ` Eric Dumazet
2010-09-20 16:59                       ` David Miller
2010-09-07  1:25     ` David Miller
  -- strict thread matches above, loose matches on Subject: below --
2010-07-22 19:12 [PATCH] Fix corruption of skb csum field in pskb_expand_head() of net/core/skbuff.c Andrea Shepard
2010-07-23  5:09 ` [PATCH net-next-2.6] net: pskb_expand_head() optimization Eric Dumazet
2010-07-25  4:06   ` David Miller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100911123140.GA1939@del.dom.local \
    --to=jarkao2@gmail.com \
    --cc=davem@davemloft.net \
    --cc=eric.dumazet@gmail.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.