netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
@ 2007-09-14  7:39 Pavel Emelyanov
  2007-09-14 12:49 ` Stephen Hemminger
       [not found] ` <46EA3AB4.7060904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
  0 siblings, 2 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2007-09-14  7:39 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Linux Netdev List, Linux Containers, devel, Daniel Lezcano

I proposed introducing a list_for_each_entry_continue_reverse
macro to be used in setup_net() when unrolling the failed
->init callback.

Here is the macro and some more cleanup in the setup_net() itself
to remove one variable from the stack :) Minor, but the code
looks nicer.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

---

I have problems with cloning repos from git.openvz.org, so
this patch comes to the yesterdays net-2.6.24 David's tree.

diff --git a/include/linux/list.h b/include/linux/list.h
index f29fc9c..ad9dcb9 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -525,6 +525,20 @@ static inline void list_splice_init_rcu(
 	     pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     prefetch(pos->member.prev), &pos->member != (head);	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
  * list_for_each_entry_from - iterate over list of given type from the current point
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 1fc513c..a9dd261 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -102,7 +102,6 @@ static int setup_net(struct net *net)
 {
 	/* Must be called with net_mutex held */
 	struct pernet_operations *ops;
-	struct list_head *ptr;
 	int error;
 
 	memset(net, 0, sizeof(struct net));
@@ -110,8 +109,7 @@ static int setup_net(struct net *net)
 	atomic_set(&net->use_count, 0);
 
 	error = 0;
-	list_for_each(ptr, &pernet_list) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry(ops, &pernet_list, list) {
 		if (ops->init) {
 			error = ops->init(net);
 			if (error < 0)
@@ -120,12 +118,12 @@ static int setup_net(struct net *net)
 	}
 out:
 	return error;
+
 out_undo:
 	/* Walk through the list backwards calling the exit functions
 	 * for the pernet modules whose init functions did not fail.
 	 */
-	for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
 		if (ops->exit)
 			ops->exit(net);
 	}

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-14  7:39 [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net Pavel Emelyanov
@ 2007-09-14 12:49 ` Stephen Hemminger
  2007-09-14 14:41   ` Eric W. Biederman
       [not found] ` <46EA3AB4.7060904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
  1 sibling, 1 reply; 13+ messages in thread
From: Stephen Hemminger @ 2007-09-14 12:49 UTC (permalink / raw)
  To: Pavel Emelyanov
  Cc: Eric W. Biederman, Linux Netdev List, Linux Containers, devel,
	Daniel Lezcano

On Fri, 14 Sep 2007 11:39:32 +0400
Pavel Emelyanov <xemul@openvz.org> wrote:

> I proposed introducing a list_for_each_entry_continue_reverse
> macro to be used in setup_net() when unrolling the failed
> ->init callback.
> 
> Here is the macro and some more cleanup in the setup_net() itself
> to remove one variable from the stack :) Minor, but the code
> looks nicer.
> 
> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>

Maybe it is time to just eliminate the init hook from the API.
It has very few users, and there is no reason the setup needed
could be done before or after registering in most cases.

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-14 12:49 ` Stephen Hemminger
@ 2007-09-14 14:41   ` Eric W. Biederman
  2007-09-14 20:07     ` Stephen Hemminger
  0 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2007-09-14 14:41 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Pavel Emelyanov, Linux Netdev List, Linux Containers, devel,
	Daniel Lezcano

Stephen Hemminger <shemminger@linux-foundation.org> writes:

> On Fri, 14 Sep 2007 11:39:32 +0400
> Pavel Emelyanov <xemul@openvz.org> wrote:
>
>> I proposed introducing a list_for_each_entry_continue_reverse
>> macro to be used in setup_net() when unrolling the failed
>> ->init callback.
>> 
>> Here is the macro and some more cleanup in the setup_net() itself
>> to remove one variable from the stack :) Minor, but the code
>> looks nicer.
>> 
>> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
>
> Maybe it is time to just eliminate the init hook from the API.
> It has very few users, and there is no reason the setup needed
> could be done before or after registering in most cases.

I guess only have 5 out of the 29 users I have in my full patchset
is few.  But that is to be expected because so far only the core
has been converted.

I looked again at the initialization to see if you had a point about
the initialization but in every instance I looked at the function
was performing work that needed to happen during the creation of
each network namespace.  So the work very much needs to be done there.

Ok looking some more I can see why this isn't obvious yet.  copy_net_ns
hasn't been merged yet, and that is where we create new network namespaces.
And call setup_net on each new network namespace.

I will take a look at that patch and see if I can come up with a
safe version of it to merge to allow for a little more transparency.

> struct net *copy_net_ns(unsigned long flags, struct net *old_net)
> {
>         struct net *new_net = NULL;
>         int err;
> 
>         get_net(old_net);
> 
>         if (!(flags & CLONE_NEWNET))
>                 return old_net;
> 
>         err = -EPERM;
>         if (!capable(CAP_SYS_ADMIN))
>                 goto out;
> 
>         err = -ENOMEM;
>         new_net = net_alloc();
>         if (!new_net)
>                 goto out;
> 
>         mutex_lock(&net_mutex);
>         err = setup_net(new_net);
>         if (err)
>                 goto out_unlock;
> 
>         net_lock();
>         list_add_tail(&new_net->list, &net_namespace_list);
>         net_unlock();
> 
> 
> out_unlock:
>         mutex_unlock(&net_mutex);
> out:
>         put_net(old_net);
>         if (err) {
>                 net_free(new_net);
>                 new_net = ERR_PTR(err);
>         }
>         return new_net;
> }

Eric


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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
       [not found] ` <46EA3AB4.7060904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
@ 2007-09-14 17:33   ` Eric W. Biederman
  0 siblings, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2007-09-14 17:33 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: Linux Containers, Linux Netdev List

Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org> writes:

> I proposed introducing a list_for_each_entry_continue_reverse
> macro to be used in setup_net() when unrolling the failed
> ->init callback.
>
> Here is the macro and some more cleanup in the setup_net() itself
> to remove one variable from the stack :) Minor, but the code
> looks nicer.
>
> Signed-off-by: Pavel Emelyanov <xemul-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>

Acked-by: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>

Eric

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-14 14:41   ` Eric W. Biederman
@ 2007-09-14 20:07     ` Stephen Hemminger
  2007-09-14 21:53       ` Eric W. Biederman
  2007-09-16 23:49       ` David Miller
  0 siblings, 2 replies; 13+ messages in thread
From: Stephen Hemminger @ 2007-09-14 20:07 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Pavel Emelyanov, Linux Netdev List, Linux Containers, devel,
	Daniel Lezcano

On Fri, 14 Sep 2007 08:41:07 -0600
ebiederm@xmission.com (Eric W. Biederman) wrote:

> Stephen Hemminger <shemminger@linux-foundation.org> writes:
> 
> > On Fri, 14 Sep 2007 11:39:32 +0400
> > Pavel Emelyanov <xemul@openvz.org> wrote:
> >
> >> I proposed introducing a list_for_each_entry_continue_reverse
> >> macro to be used in setup_net() when unrolling the failed
> >> ->init callback.
> >> 
> >> Here is the macro and some more cleanup in the setup_net() itself
> >> to remove one variable from the stack :) Minor, but the code
> >> looks nicer.
> >> 
> >> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
> >
> > Maybe it is time to just eliminate the init hook from the API.
> > It has very few users, and there is no reason the setup needed
> > could be done before or after registering in most cases.
> 
> I guess only have 5 out of the 29 users I have in my full patchset
> is few.  But that is to be expected because so far only the core
> has been converted.
> 
> I looked again at the initialization to see if you had a point about
> the initialization but in every instance I looked at the function
> was performing work that needed to happen during the creation of
> each network namespace.  So the work very much needs to be done there.
> 
> Ok looking some more I can see why this isn't obvious yet.  copy_net_ns
> hasn't been merged yet, and that is where we create new network namespaces.
> And call setup_net on each new network namespace.
> 
> I will take a look at that patch and see if I can come up with a
> safe version of it to merge to allow for a little more transparency.

Could we just make it so dev->init is not allowed to fail? Then it
can be a void function and the nasty unwind code can go?

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-14 20:07     ` Stephen Hemminger
@ 2007-09-14 21:53       ` Eric W. Biederman
  2007-09-16 23:49       ` David Miller
  1 sibling, 0 replies; 13+ messages in thread
From: Eric W. Biederman @ 2007-09-14 21:53 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Pavel Emelyanov, Linux Netdev List, Linux Containers, devel,
	Daniel Lezcano

Stephen Hemminger <shemminger@linux-foundation.org> writes:

> Could we just make it so dev->init is not allowed to fail? Then it
> can be a void function and the nasty unwind code can go?

Unfortunately we need to allocate memory, and perform other operations
that can fail.  That's the nature of the problem.

So I think not allowing init to fail would be optimizing for the wrong
the case.  Allowing init to fail makes the rest of the code simpler
because we don't have to perform the impossible when the highly
unlikely happens.

The ugly unwind is only about 5 lines of code that never need to
change (except for beautification).  So I don't think the cost
is prohibitive.

Eric



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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-14 20:07     ` Stephen Hemminger
  2007-09-14 21:53       ` Eric W. Biederman
@ 2007-09-16 23:49       ` David Miller
  2007-09-17  0:06         ` Eric W. Biederman
  1 sibling, 1 reply; 13+ messages in thread
From: David Miller @ 2007-09-16 23:49 UTC (permalink / raw)
  To: shemminger; +Cc: ebiederm, xemul, netdev, containers, devel, dlezcano

From: Stephen Hemminger <shemminger@linux-foundation.org>
Date: Fri, 14 Sep 2007 22:07:14 +0200

> Could we just make it so dev->init is not allowed to fail? Then it
> can be a void function and the nasty unwind code can go?

Someone (not me :-) need to do an audit to find all current
users of this function and determine if they all can live
without returning errors.

If so, sure let's make the change and simplify things.

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-16 23:49       ` David Miller
@ 2007-09-17  0:06         ` Eric W. Biederman
  2007-09-17  0:07           ` David Miller
  0 siblings, 1 reply; 13+ messages in thread
From: Eric W. Biederman @ 2007-09-17  0:06 UTC (permalink / raw)
  To: David Miller; +Cc: shemminger, xemul, netdev, containers, devel, dlezcano

David Miller <davem@davemloft.net> writes:

> From: Stephen Hemminger <shemminger@linux-foundation.org>
> Date: Fri, 14 Sep 2007 22:07:14 +0200
>
>> Could we just make it so dev->init is not allowed to fail? Then it
>> can be a void function and the nasty unwind code can go?
>
> Someone (not me :-) need to do an audit to find all current
> users of this function and determine if they all can live
> without returning errors.
>
> If so, sure let's make the change and simplify things.

I did that audit when I replied to Stephen the first time and I just
redid it to verify myself.  We are calling functions that can fail
from the init function (kmalloc in the most common).  So the
init function can fail.

So short of adding a bunch of BUG_ON's to the kernel to trap those
failure cases we can't remove the backwards list walk.  Especially
since I can initiate this code path as root by calling 
"clone(CLONE_NEWNET...)".

Eric

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-17  0:06         ` Eric W. Biederman
@ 2007-09-17  0:07           ` David Miller
  0 siblings, 0 replies; 13+ messages in thread
From: David Miller @ 2007-09-17  0:07 UTC (permalink / raw)
  To: ebiederm; +Cc: shemminger, xemul, netdev, containers, devel, dlezcano

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Sun, 16 Sep 2007 18:06:00 -0600

> I did that audit when I replied to Stephen the first time and I just
> redid it to verify myself.  We are calling functions that can fail
> from the init function (kmalloc in the most common).  So the
> init function can fail.
> 
> So short of adding a bunch of BUG_ON's to the kernel to trap those
> failure cases we can't remove the backwards list walk.  Especially
> since I can initiate this code path as root by calling 
> "clone(CLONE_NEWNET...)".

I just noticed that posting and thanks for reiterating.

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

* [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
@ 2007-09-17 11:02 Pavel Emelyanov
  2007-09-17 13:07 ` Eric W. Biederman
  0 siblings, 1 reply; 13+ messages in thread
From: Pavel Emelyanov @ 2007-09-17 11:02 UTC (permalink / raw)
  To: David Miller; +Cc: Eric W. Biederman, Linux Netdev List, devel

I proposed introducing a list_for_each_entry_continue_reverse
macro to be used in setup_net() when unrolling the failed
->init callback.

Here is the macro and some more cleanup in the setup_net() itself
to remove one variable from the stack :) Minor, but the code
looks nicer.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

---

 include/linux/list.h     |   14 ++++++++++++++
 net/core/net_namespace.c |    8 +++-----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/include/linux/list.h b/include/linux/list.h
index f29fc9c..ad9dcb9 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -525,6 +525,20 @@ static inline void list_splice_init_rcu(
 	     pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     prefetch(pos->member.prev), &pos->member != (head);	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
  * list_for_each_entry_from - iterate over list of given type from the current point
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 1fc513c..a9dd261 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -102,7 +102,6 @@ static int setup_net(struct net *net)
 {
 	/* Must be called with net_mutex held */
 	struct pernet_operations *ops;
-	struct list_head *ptr;
 	int error;
 
 	memset(net, 0, sizeof(struct net));
@@ -110,8 +109,7 @@ static int setup_net(struct net *net)
 	atomic_set(&net->use_count, 0);
 
 	error = 0;
-	list_for_each(ptr, &pernet_list) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry(ops, &pernet_list, list) {
 		if (ops->init) {
 			error = ops->init(net);
 			if (error < 0)
@@ -120,12 +118,12 @@ static int setup_net(struct net *net)
 	}
 out:
 	return error;
+
 out_undo:
 	/* Walk through the list backwards calling the exit functions
 	 * for the pernet modules whose init functions did not fail.
 	 */
-	for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
 		if (ops->exit)
 			ops->exit(net);
 	}

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-17 11:02 Pavel Emelyanov
@ 2007-09-17 13:07 ` Eric W. Biederman
  2007-09-17 13:54   ` Pavel Emelyanov
  2007-09-18  1:58   ` David Miller
  0 siblings, 2 replies; 13+ messages in thread
From: Eric W. Biederman @ 2007-09-17 13:07 UTC (permalink / raw)
  To: Pavel Emelyanov; +Cc: David Miller, Linux Netdev List, devel

Pavel Emelyanov <xemul@openvz.org> writes:

> I proposed introducing a list_for_each_entry_continue_reverse
> macro to be used in setup_net() when unrolling the failed
> ->init callback.
>
> Here is the macro and some more cleanup in the setup_net() itself
> to remove one variable from the stack :) Minor, but the code
> looks nicer.
>
> Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

Pavel if you are going down this route.  Could you look at
cleanup_net as well.  The reverse walk there could probably
benefit from being list_for_each_entry_reverse.

Eric


>
> ---
>
>  include/linux/list.h     |   14 ++++++++++++++
>  net/core/net_namespace.c |    8 +++-----
>  2 files changed, 17 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/list.h b/include/linux/list.h
> index f29fc9c..ad9dcb9 100644
> --- a/include/linux/list.h
> +++ b/include/linux/list.h
> @@ -525,6 +525,20 @@ static inline void list_splice_init_rcu(
>  	     pos = list_entry(pos->member.next, typeof(*pos), member))
>  
>  /**
> + * list_for_each_entry_continue_reverse - iterate backwards from the given
> point
> + * @pos:	the type * to use as a loop cursor.
> + * @head:	the head for your list.
> + * @member:	the name of the list_struct within the struct.
> + *
> + * Start to iterate over list of given type backwards, continuing after
> + * the current position.
> + */
> +#define list_for_each_entry_continue_reverse(pos, head, member) \
> +	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
> +	     prefetch(pos->member.prev), &pos->member != (head);	\
> +	     pos = list_entry(pos->member.prev, typeof(*pos), member))
> +
> +/**
>   * list_for_each_entry_from - iterate over list of given type from the current
> point
>   * @pos:	the type * to use as a loop cursor.
>   * @head:	the head for your list.
> diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
> index 1fc513c..a9dd261 100644
> --- a/net/core/net_namespace.c
> +++ b/net/core/net_namespace.c
> @@ -102,7 +102,6 @@ static int setup_net(struct net *net)
>  {
>  	/* Must be called with net_mutex held */
>  	struct pernet_operations *ops;
> -	struct list_head *ptr;
>  	int error;
>  
>  	memset(net, 0, sizeof(struct net));
> @@ -110,8 +109,7 @@ static int setup_net(struct net *net)
>  	atomic_set(&net->use_count, 0);
>  
>  	error = 0;
> -	list_for_each(ptr, &pernet_list) {
> -		ops = list_entry(ptr, struct pernet_operations, list);
> +	list_for_each_entry(ops, &pernet_list, list) {
>  		if (ops->init) {
>  			error = ops->init(net);
>  			if (error < 0)
> @@ -120,12 +118,12 @@ static int setup_net(struct net *net)
>  	}
>  out:
>  	return error;
> +
>  out_undo:
>  	/* Walk through the list backwards calling the exit functions
>  	 * for the pernet modules whose init functions did not fail.
>  	 */
> -	for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
> -		ops = list_entry(ptr, struct pernet_operations, list);
> +	list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
>  		if (ops->exit)
>  			ops->exit(net);
>  	}

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

* [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-17 13:07 ` Eric W. Biederman
@ 2007-09-17 13:54   ` Pavel Emelyanov
  2007-09-18  1:58   ` David Miller
  1 sibling, 0 replies; 13+ messages in thread
From: Pavel Emelyanov @ 2007-09-17 13:54 UTC (permalink / raw)
  To: Eric W. Biederman, David Miller; +Cc: Linux Netdev List, devel

[snip]

> Pavel if you are going down this route.  Could you look at
> cleanup_net as well.  The reverse walk there could probably
> benefit from being list_for_each_entry_reverse.

Oh! Thanks a lot ;) Here's the new patch.

Log:

I proposed introducing a list_for_each_entry_continue_reverse
macro to be used in setup_net() when unrolling the failed
->init callback.

Here is the macro and some more cleanup in the setup_net() itself
to remove one variable from the stack :) Minor, but the code
looks nicer.

Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

---

diff --git a/include/linux/list.h b/include/linux/list.h
index f29fc9c..ad9dcb9 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -525,6 +525,20 @@ static inline void list_splice_init_rcu(
 	     pos = list_entry(pos->member.next, typeof(*pos), member))
 
 /**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member)		\
+	for (pos = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     prefetch(pos->member.prev), &pos->member != (head);	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
  * list_for_each_entry_from - iterate over list of given type from the current point
  * @pos:	the type * to use as a loop cursor.
  * @head:	the head for your list.
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 1fc513c..0e6cb02 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -56,7 +56,6 @@ static void net_free(struct net *net)
 static void cleanup_net(struct work_struct *work)
 {
 	struct pernet_operations *ops;
-	struct list_head *ptr;
 	struct net *net;
 
 	net = container_of(work, struct net, work);
@@ -69,8 +68,7 @@ static void cleanup_net(struct work_stru
 	net_unlock();
 
 	/* Run all of the network namespace exit methods */
-	list_for_each_prev(ptr, &pernet_list) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry_reverse(ops, &pernet_list, list) {
 		if (ops->exit)
 			ops->exit(net);
 	}
@@ -102,7 +100,6 @@ static int setup_net(struct net *net)
 {
 	/* Must be called with net_mutex held */
 	struct pernet_operations *ops;
-	struct list_head *ptr;
 	int error;
 
 	memset(net, 0, sizeof(struct net));
@@ -110,8 +107,7 @@ static int setup_net(struct net *net)
 	atomic_set(&net->use_count, 0);
 
 	error = 0;
-	list_for_each(ptr, &pernet_list) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry(ops, &pernet_list, list) {
 		if (ops->init) {
 			error = ops->init(net);
 			if (error < 0)
@@ -120,12 +116,12 @@ static int setup_net(struct net *net)
 	}
 out:
 	return error;
+
 out_undo:
 	/* Walk through the list backwards calling the exit functions
 	 * for the pernet modules whose init functions did not fail.
 	 */
-	for (ptr = ptr->prev; ptr != &pernet_list; ptr = ptr->prev) {
-		ops = list_entry(ptr, struct pernet_operations, list);
+	list_for_each_entry_continue_reverse(ops, &pernet_list, list) {
 		if (ops->exit)
 			ops->exit(net);
 	}

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

* Re: [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net
  2007-09-17 13:07 ` Eric W. Biederman
  2007-09-17 13:54   ` Pavel Emelyanov
@ 2007-09-18  1:58   ` David Miller
  1 sibling, 0 replies; 13+ messages in thread
From: David Miller @ 2007-09-18  1:58 UTC (permalink / raw)
  To: ebiederm; +Cc: xemul, netdev, devel

From: ebiederm@xmission.com (Eric W. Biederman)
Date: Mon, 17 Sep 2007 07:07:42 -0600

> Pavel if you are going down this route.  Could you look at
> cleanup_net as well.  The reverse walk there could probably
> benefit from being list_for_each_entry_reverse.

Pavel please resubmit this work after everything has been
resolved, thanks.

If you have already, please resend as I don't have a copy.

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

end of thread, other threads:[~2007-09-18  1:58 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-09-14  7:39 [PATCH][NETNS] Use list_for_each_entry_continue_reverse in setup_net Pavel Emelyanov
2007-09-14 12:49 ` Stephen Hemminger
2007-09-14 14:41   ` Eric W. Biederman
2007-09-14 20:07     ` Stephen Hemminger
2007-09-14 21:53       ` Eric W. Biederman
2007-09-16 23:49       ` David Miller
2007-09-17  0:06         ` Eric W. Biederman
2007-09-17  0:07           ` David Miller
     [not found] ` <46EA3AB4.7060904-GEFAQzZX7r8dnm+yROfE0A@public.gmane.org>
2007-09-14 17:33   ` Eric W. Biederman
  -- strict thread matches above, loose matches on Subject: below --
2007-09-17 11:02 Pavel Emelyanov
2007-09-17 13:07 ` Eric W. Biederman
2007-09-17 13:54   ` Pavel Emelyanov
2007-09-18  1:58   ` 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).