Skip to contentSkip to conversation

fib_trie: more whitespace cleanup

PATCH Applied Stephen Hemminger 4 participants 20 messages Jan 23, 2008 – Feb 1, 2008 1 message not in the archive

Subsystems (3)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

PATCH 1/5 fib_trie: more whitespace cleanup

Remove extra blank lines.

net/ipv4/fib_trie.c +0 -6
@@ -447,7 +447,6 @@ static void tnode_put_child_reorg(struct
 
 	BUG_ON(i >= 1<<tn->bits);
 
-
 	/* update emptyChildren */
 	if (n == NULL && chi != NULL)
 		tn->empty_children++;
@@ -1303,7 +1302,6 @@ err:
 	return err;
 }
 
-
 /* should be called with rcu_read_lock */
 static int check_leaf(struct trie *t, struct leaf *l,
 		      t_key key,  const struct flowi *flp,
@@ -1718,7 +1716,6 @@ static struct leaf *leaf_walk_rcu(struct
 	return NULL; /* Root of trie */
 }
 
-
 static struct leaf *trie_firstleaf(struct trie *t)
 {
 	struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
@@ -1846,7 +1843,6 @@ static int fn_trie_dump_fa(t_key key, in
 {
 	int i, s_i;
 	struct fib_alias *fa;
-
 	__be32 xkey = htonl(key);
 
 	s_i = cb->args[4];
@@ -1879,7 +1875,6 @@ static int fn_trie_dump_fa(t_key key, in
 	return skb->len;
 }
 
-
 static int fn_trie_dump_leaf(struct leaf *l, struct fib_table *tb,
 			struct sk_buff *skb, struct netlink_callback *cb)
 {
@@ -2385,7 +2380,6 @@ static int fib_trie_seq_show(struct seq_
 		struct leaf *l = (struct leaf *) n;
 		struct leaf_info *li;
 		struct hlist_node *node;
-
 		__be32 val = htonl(l->key);
 
 		seq_indent(seq, iter->depth);
Signature · 1 line
Stephen Hemminger <[email protected]>
#3 lore raw

PATCH 2/5 fib_trie: remove unneeded NULL check

In reply to a message not in the archive

Since fib_route_seq_show now uses hlist_for_each_entry(), the leaf info can not be NULL.

net/ipv4/fib_trie.c +0 -3
@@ -2474,9 +2474,6 @@ static int fib_route_seq_show(struct seq
 		struct fib_alias *fa;
 		__be32 mask, prefix;
 
-		if (!li)
-			continue;
-
 		mask = inet_make_mask(li->plen);
 		prefix = htonl(l->key);
 
Signature · 1 line
Stephen Hemminger <[email protected]>
#5 lore raw

PATCH 3/5 fib_trie: dump doesnt use RCU

In reply to a message not in the archive

Since fib dump (via netlink) holds the RTNL mutex, it is unnecessary to use RCU, and it is impossible to get truncated (-EBUSY) result.

net/ipv4/fib_trie.c +12 -25
@@ -1684,7 +1684,7 @@ static int trie_flush_leaf(struct trie *
  * Scan for the next right leaf starting at node p->child[idx]
  * Since we have back pointer, no recursion necessary.
  */
-static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
+static struct leaf *leaf_walk(struct tnode *p, struct node *c)
 {
 	do {
 		t_key idx;
@@ -1695,7 +1695,7 @@ static struct leaf *leaf_walk_rcu(struct
 			idx = 0;
 
 		while (idx < 1u << p->bits) {
-			c = tnode_get_child_rcu(p, idx++);
+			c = tnode_get_child(p, idx++);
 			if (!c)
 				continue;
 
@@ -1711,14 +1711,14 @@ static struct leaf *leaf_walk_rcu(struct
 
 		/* Node empty, walk back up to parent */
 		c = (struct node *) p;
-	} while ( (p = node_parent_rcu(c)) != NULL);
+	} while ( (p = node_parent(c)) != NULL);
 
 	return NULL; /* Root of trie */
 }
 
 static struct leaf *trie_firstleaf(struct trie *t)
 {
-	struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
+	struct tnode *n = (struct tnode *) t->trie;
 
 	if (!n)
 		return NULL;
@@ -1726,7 +1726,7 @@ static struct leaf *trie_firstleaf(struc
 	if (IS_LEAF(n))          /* trie is just a leaf */
 		return (struct leaf *) n;
 
-	return leaf_walk_rcu(n, NULL);
+	return leaf_walk(n, NULL);
 }
 
 static struct leaf *trie_nextleaf(struct leaf *l)
@@ -1737,7 +1737,7 @@ static struct leaf *trie_nextleaf(struct
 	if (!p)
 		return NULL;	/* trie with just one leaf */
 
-	return leaf_walk_rcu(p, c);
+	return leaf_walk(p, c);
 }
 
 /*
@@ -1848,9 +1848,7 @@ static int fn_trie_dump_fa(t_key key, in
 	s_i = cb->args[4];
 	i = 0;
 
-	/* rcu_read_lock is hold by caller */
-
-	list_for_each_entry_rcu(fa, fah, fa_list) {
+	list_for_each_entry(fa, fah, fa_list) {
 		if (i < s_i) {
 			i++;
 			continue;
@@ -1885,8 +1883,7 @@ static int fn_trie_dump_leaf(struct leaf
 	s_i = cb->args[3];
 	i = 0;
 
-	/* rcu_read_lock is hold by caller */
-	hlist_for_each_entry_rcu(li, node, &l->list, hlist) {
+	hlist_for_each_entry(li, node, &l->list, hlist) {
 		if (i < s_i) {
 			i++;
 			continue;
@@ -1916,35 +1913,25 @@ static int fn_trie_dump(struct fib_table
 	struct trie *t = (struct trie *) tb->tb_data;
 	t_key key = cb->args[2];
 
-	rcu_read_lock();
+	ASSERT_RTNL();
+
 	/* Dump starting at last key.
 	 * Note: 0.0.0.0/0 (ie default) is first key.
 	 */
 	if (!key)
 		l = trie_firstleaf(t);
-	else {
+	else
 		l = fib_find_node(t, key);
-		if (!l) {
-			/* The table changed during the dump, rather than
-			 * giving partial data, just make application retry.
-			 */
-			rcu_read_unlock();
-			return -EBUSY;
-		}
-	}
 
 	while (l) {
 		cb->args[2] = l->key;
-		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
-			rcu_read_unlock();
+		if (fn_trie_dump_leaf(l, tb, skb, cb) < 0)
 			return -1;
-		}
 
 		l = trie_nextleaf(l);
 		memset(&cb->args[3], 0,
 		       sizeof(cb->args) - 3*sizeof(cb->args[0]));
 	}
-	rcu_read_unlock();
 
 	return skb->len;
 }
Signature · 1 line
Stephen Hemminger <[email protected]>
maintainer
#6 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

From: Stephen Hemminger <[email protected]>
Date: Wed, 23 Jan 2008 14:48:47 -0800

Quoted 4 lines

Since fib dump (via netlink) holds the RTNL mutex, it is unnecessary to use RCU, and it is impossible to get truncated (-EBUSY) result.

You tested this patch, right? :-/

The whole reason we need the nlk->cb[] state is to hold things across multiple recvmsg() calls that might be necessary to obtain the full dump.

rtnetlink goes:

	rtnl_lock();
	netlink_rcv_skb(skb, &rtnetlink_rcv_msg);

...
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) {
...

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		struct sock *rtnl;
		rtnl_dumpit_func dumpit;

		dumpit = rtnl_get_dumpit(family, type);
		if (dumpit == NULL)
			return -EOPNOTSUPP;

		__rtnl_unlock();
		rtnl = net->rtnl;
		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
		rtnl_lock();
		return err;

(NOTE: Drops RTNL semaphore for netlink_dump_start() call)

...
int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct nlmsghdr *nlh,
int (*dump)(struct sk_buff *skb,
struct netlink_callback *),
int (*done)(struct netlink_callback *))
{
...

	cb->dump = dump;
	cb->done = done;
	cb->nlh = nlh;
	atomic_inc(&skb->users);
	cb->skb = skb;
 ...
	mutex_lock(nlk->cb_mutex);
 ...
	nlk->cb = cb;
	mutex_unlock(nlk->cb_mutex);

	netlink_dump(sk);

...

static int netlink_dump(struct sock *sk)
{
...

	mutex_lock(nlk->cb_mutex);
 ...
	len = cb->dump(skb, cb);

	if (len > 0) {
		mutex_unlock(nlk->cb_mutex);
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, len);
		return 0;
	}

(NOTE: Therefore cb->dump() runs without RTNL semaphore held)

...
static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
...

	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
		netlink_dump(sk);

...

Therefore, that RTNL assertion you added should have triggered on any dump you may have tried since ->dump() is always invoked without the RTNL semaphore since rtnetlink drops it around the ->dump() call and the call chain for this fib_trie cause would be:

inet_dump_fib()
fn_trie_dump()

and nothing in that code path retakes the RTNL semaphore.

What test did you run to validate this patch for correctness?

#7 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

Quoted 93 lines · David Miller

From: Stephen Hemminger <[email protected]>
Date: Wed, 23 Jan 2008 14:48:47 -0800

Quoted 5 lines

Since fib dump (via netlink) holds the RTNL mutex, it is unnecessary to use RCU, and it is impossible to get truncated (-EBUSY) result.

You tested this patch, right? :-/

The whole reason we need the nlk->cb[] state is to hold things across multiple recvmsg() calls that might be necessary to obtain the full dump.

rtnetlink goes:

	rtnl_lock();
	netlink_rcv_skb(skb, &rtnetlink_rcv_msg);

...
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) {
...

	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
		struct sock *rtnl;
		rtnl_dumpit_func dumpit;

		dumpit = rtnl_get_dumpit(family, type);
		if (dumpit == NULL)
			return -EOPNOTSUPP;

		__rtnl_unlock();
		rtnl = net->rtnl;
		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
		rtnl_lock();
		return err;

(NOTE: Drops RTNL semaphore for netlink_dump_start() call)

...
int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct nlmsghdr *nlh,
int (*dump)(struct sk_buff *skb,
struct netlink_callback *),
int (*done)(struct netlink_callback *))
{
...

	cb->dump = dump;
	cb->done = done;
	cb->nlh = nlh;
	atomic_inc(&skb->users);
	cb->skb = skb;
 ...
	mutex_lock(nlk->cb_mutex);
 ...
	nlk->cb = cb;
	mutex_unlock(nlk->cb_mutex);

	netlink_dump(sk);

...

static int netlink_dump(struct sock *sk)
{
...

	mutex_lock(nlk->cb_mutex);
 ...
	len = cb->dump(skb, cb);

	if (len > 0) {
		mutex_unlock(nlk->cb_mutex);
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, len);
		return 0;
	}

(NOTE: Therefore cb->dump() runs without RTNL semaphore held)

...
static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags)
{
...

	if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
		netlink_dump(sk);

...

Therefore, that RTNL assertion you added should have triggered on any dump you may have tried since ->dump() is always invoked without the RTNL semaphore since rtnetlink drops it around the ->dump() call and the call chain for this fib_trie cause would be:

Quoted 4 lines

inet_dump_fib()
fn_trie_dump()

and nothing in that code path retakes the RTNL semaphore.

Actually we're always holding the rtnl during dumps, nlk->cb_mutex points to rtnl_mutex in case of rtnetlink. It used to be held only during the first ->dump invocation and not on continuations, but I changed this a few versions ago.

maintainer
#8 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

From: Patrick McHardy <[email protected]>
Date: Thu, 24 Jan 2008 07:41:08 +0100

Quoted 7 lines
Quoted 1 line · David Miller

and nothing in that code path retakes the RTNL semaphore.

Actually we're always holding the rtnl during dumps, nlk->cb_mutex points to rtnl_mutex in case of rtnetlink. It used to be held only during the first ->dump invocation and not on continuations, but I changed this a few versions ago.

My bad. Thanks for the correction Patrick.

But continuations can occur on subsequent recvmsg() calls, does it return to userspace with the mutex held? If so I'm pretty sure that's not allowed.

#9 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

Quoted 14 lines · David Miller

From: Patrick McHardy <[email protected]>
Date: Thu, 24 Jan 2008 07:41:08 +0100

Quoted 9 lines
Quoted 2 lines · David Miller

and nothing in that code path retakes the RTNL semaphore.

Actually we're always holding the rtnl during dumps, nlk->cb_mutex points to rtnl_mutex in case of rtnetlink. It used to be held only during the first ->dump invocation and not on continuations, but I changed this a few versions ago.

Quoted 6 lines

My bad. Thanks for the correction Patrick.

But continuations can occur on subsequent recvmsg() calls, does it return to userspace with the mutex held? If so I'm pretty sure that's not allowed.

No, the mutex is dropped between different ->dump invocations.

maintainer
#10 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

From: Patrick McHardy <[email protected]>
Date: Thu, 24 Jan 2008 07:47:39 +0100

Quoted 14 lines
Quoted 13 lines · David Miller

From: Patrick McHardy <[email protected]>
Date: Thu, 24 Jan 2008 07:41:08 +0100

Quoted 9 lines
Quoted 2 lines · David Miller

and nothing in that code path retakes the RTNL semaphore.

Actually we're always holding the rtnl during dumps, nlk->cb_mutex points to rtnl_mutex in case of rtnetlink. It used to be held only during the first ->dump invocation and not on continuations, but I changed this a few versions ago.

Quoted 7 lines
Quoted 5 lines

My bad. Thanks for the correction Patrick.

But continuations can occur on subsequent recvmsg() calls, does it return to userspace with the mutex held? If so I'm pretty sure that's not allowed.

No, the mutex is dropped between different ->dump invocations.

Ok, great.

This does mean, however, that the RTNL semaphore is dropped between ->dump() invocations on the same nlk->cb[] instance.

And that has implications for the shortcut Stephen is taking.

Stephen's patch assumes that during a (top-level) dump the table cannot change. And by the above, we can only conclude that it can in fact change between ->dump() calls for the same top-level dump run.

So the removal of the -EBUSY code block in his patch isn't valid.

#11 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

In reply to Patrick McHardy
Quoted 97 lines · Patrick McHardy
Quoted 96 lines · David Miller

From: Stephen Hemminger <[email protected]>
Date: Wed, 23 Jan 2008 14:48:47 -0800

Quoted 5 lines

Since fib dump (via netlink) holds the RTNL mutex, it is unnecessary to use RCU, and it is impossible to get truncated (-EBUSY) result.

You tested this patch, right? :-/

The whole reason we need the nlk->cb[] state is to hold things across multiple recvmsg() calls that might be necessary to obtain the full dump.

rtnetlink goes:

    rtnl_lock();
    netlink_rcv_skb(skb, &rtnetlink_rcv_msg);

...
static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) {
...

    if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
        struct sock *rtnl;
        rtnl_dumpit_func dumpit;

        dumpit = rtnl_get_dumpit(family, type);
        if (dumpit == NULL)
            return -EOPNOTSUPP;

        __rtnl_unlock();
        rtnl = net->rtnl;
        err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
        rtnl_lock();
        return err;

(NOTE: Drops RTNL semaphore for netlink_dump_start() call)

...
int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct nlmsghdr *nlh,
int (*dump)(struct sk_buff *skb,
struct netlink_callback *),
int (*done)(struct netlink_callback *))
{
...

    cb->dump = dump;
    cb->done = done;
    cb->nlh = nlh;
    atomic_inc(&skb->users);
    cb->skb = skb;
 ...
    mutex_lock(nlk->cb_mutex);
 ...
    nlk->cb = cb;
    mutex_unlock(nlk->cb_mutex);

    netlink_dump(sk);

...

static int netlink_dump(struct sock *sk)
{
...

    mutex_lock(nlk->cb_mutex);
 ...
    len = cb->dump(skb, cb);

    if (len > 0) {
        mutex_unlock(nlk->cb_mutex);
        skb_queue_tail(&sk->sk_receive_queue, skb);
        sk->sk_data_ready(sk, len);
        return 0;
    }

(NOTE: Therefore cb->dump() runs without RTNL semaphore held)

...
static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
struct msghdr *msg, size_t len,
int flags)
{
...

    if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)
        netlink_dump(sk);

...

Therefore, that RTNL assertion you added should have triggered on any dump you may have tried since ->dump() is always invoked without the RTNL semaphore since rtnetlink drops it around the ->dump() call and the call chain for this fib_trie cause would be:

inet_dump_fib()
fn_trie_dump()

Quoted 9 lines
Quoted 1 line

and nothing in that code path retakes the RTNL semaphore.

Actually we're always holding the rtnl during dumps, nlk->cb_mutex points to rtnl_mutex in case of rtnetlink. It used to be held only during the first ->dump invocation and not on continuations, but I changed this a few versions
ago.

Yes, I tested, no the assert didn't hit... Actually, the reason I went down this path was because I couldn't trigger -EBUSY with concurrent updates.

P.s: I checked and Quagga handles -EAGAIN, so if you need an error code that would be the one to use.

maintainer
#12 lore raw

Re: [IPV4 3/5] fib_trie: dump doesnt use RCU

From: Stephen Hemminger <[email protected]>
Date: Wed, 23 Jan 2008 22:45:02 -0800

Quoted 6 lines

Yes, I tested, no the assert didn't hit... Actually, the reason I went down this path was
because I couldn't trigger -EBUSY with concurrent updates.

P.s: I checked and Quagga handles -EAGAIN, so if you need an error code that would be the one to use.

Ok, but see my other email, the -EBUSY block can't be removed.

Even though for any given ->dump() call RTNL is held, it is dropped before the next ->dump() call on the same piece of nlk->cb[] state.

So the node for the nlk->cb->args[2] key can go away due to an intervening table change.

#13 lore raw

PATCH 1/1 fib_trie: rescan if key is lost during dump

Normally during a dump the key of the last dumped entry is used for continuation, but since lock is dropped it might be lost. In that case fallback to the old counter based N^2 behaviour. This means the dump will end up skipping some routes which matches what FIB_HASH does.

include/linux/netlink.h +1 -1
@@ -219,7 +219,7 @@ struct netlink_callback
 	int		(*dump)(struct sk_buff * skb, struct netlink_callback *cb);
 	int		(*done)(struct netlink_callback *cb);
 	int		family;
-	long		args[5];
+	long		args[6];
 };
 
 struct netlink_notify
net/ipv4/fib_trie.c +32 -17

118 lines not on this page · raw message

#14 lore raw

Re: [PATCH] fib_trie: rescan if key is lost during dump

Quoted 6 lines · Stephen Hemminger

Normally during a dump the key of the last dumped entry is used for continuation, but since lock is dropped it might be lost. In that case fallback to the old counter based N^2 behaviour. This means the dump will end up skipping some routes which matches what FIB_HASH does.

...

net/ipv4/fib_trie.c static int fn_trie_dump(struct fib_table · line 1936

Quoted 7 lines
net/ipv4/fib_trie.c +1 -0
@@ -1918,35 +1931,37 @@ static int fn_trie_dump(struct fib_table
 	struct leaf *l;
 	struct trie *t = (struct trie *) tb->tb_data;
 	t_key key = cb->args[2];
+	int count = cb->args[3];
 
 	rcu_read_lock();

Sorry, but I lost the point: is rtnl held or not held here at the moment? If held, how this rcu_read_lock can help? Maybe some additional comment in the code?

Thanks,
Jarek P.

#15 lore raw

Re: [PATCH] fib_trie: rescan if key is lost during dump

Quoted 14 lines · On Fri, 25 Jan 2008 09:23:00 +0100 Jarek Poplawski <[email protected]> wrote:
Quoted 6 lines · Stephen Hemminger

Normally during a dump the key of the last dumped entry is used for continuation, but since lock is dropped it might be lost. In that case fallback to the old counter based N^2 behaviour. This means the dump will end up skipping some routes which matches what FIB_HASH does.

...

Quoted 6 lines
net/ipv4/fib_trie.c +1 -0
@@ -1918,35 +1931,37 @@ static int fn_trie_dump(struct fib_table
 	struct leaf *l;
 	struct trie *t = (struct trie *) tb->tb_data;
 	t_key key = cb->args[2];
+	int count = cb->args[3];
 
Quoted 8 lines

net/ipv4/fib_trie.c static int fn_trie_dump(struct fib_table · line 1936

Quoted 1 line
net/ipv4/fib_trie.c +0 -0
 	rcu_read_lock();

Sorry, but I lost the point: is rtnl held or not held here at the moment? If held, how this rcu_read_lock can help? Maybe some additional comment in the code?

Thanks,
Jarek P.

There are two different issues, (therefore two different patches).
1. How to handle multipart resume when the key was deleted during the period the lock was dropped.

That is what this patch addresses.

2. RCU is unnecessary here because of use of RTNL. I am going to defer on this till after #1. That patch is much less important.

Signature · 1 line
Stephen Hemminger <[email protected]>
#16 lore raw

Re: [PATCH] fib_trie: rescan if key is lost during dump

On Fri, Jan 25, 2008 at 08:13:15AM -0800, Stephen Hemminger wrote:
...

Quoted 2 lines

2. RCU is unnecessary here because of use of RTNL. I am going to defer on this till after #1. That patch is much less important.

Thanks! (I've started to suspect another advanced RCU trick already...)

Jarek P.

maintainer Applied
#17 lore raw

Re: [PATCH] fib_trie: rescan if key is lost during dump

In reply to Stephen Hemminger

From: Stephen Hemminger <[email protected]>
Date: Thu, 24 Jan 2008 13:51:12 -0800

Quoted 6 lines

Normally during a dump the key of the last dumped entry is used for continuation, but since lock is dropped it might be lost. In that case fallback to the old counter based N^2 behaviour. This means the dump will end up skipping some routes which matches what FIB_HASH does.

Applied, thanks.

#20 lore raw

PATCH 5/5 fib_semantics: sparse warnings

In reply to a message not in the archive

The magic macro change_nexthops introduces a variable nh which overlaps previous declaration of nh.

net/ipv4/fib_semantics.c +9 -8
@@ -1059,14 +1059,14 @@ int fib_sync_down(__be32 local, struct n
 		unsigned int hash = fib_devindex_hashfn(dev->ifindex);
 		struct hlist_head *head = &fib_info_devhash[hash];
 		struct hlist_node *node;
-		struct fib_nh *nh;
+		struct fib_nh *nh1;
 
-		hlist_for_each_entry(nh, node, head, nh_hash) {
-			struct fib_info *fi = nh->nh_parent;
+		hlist_for_each_entry(nh1, node, head, nh_hash) {
+			struct fib_info *fi = nh1->nh_parent;
 			int dead;
 
 			BUG_ON(!fi->fib_nhs);
-			if (nh->nh_dev != dev || fi == prev_fi)
+			if (nh1->nh_dev != dev || fi == prev_fi)
 				continue;
 			prev_fi = fi;
 			dead = 0;
@@ -1091,6 +1091,7 @@ int fib_sync_down(__be32 local, struct n
 				}
 #endif
 			} endfor_nexthops(fi)
+
 			if (dead == fi->fib_nhs) {
 				fi->fib_flags |= RTNH_F_DEAD;
 				ret++;
@@ -1114,7 +1115,7 @@ int fib_sync_up(struct net_device *dev)
 	unsigned int hash;
 	struct hlist_head *head;
 	struct hlist_node *node;
-	struct fib_nh *nh;
+	struct fib_nh *nh1;
 	int ret;
 
 	if (!(dev->flags&IFF_UP))
@@ -1125,12 +1126,12 @@ int fib_sync_up(struct net_device *dev)
 	head = &fib_info_devhash[hash];
 	ret = 0;
 
-	hlist_for_each_entry(nh, node, head, nh_hash) {
-		struct fib_info *fi = nh->nh_parent;
+	hlist_for_each_entry(nh1, node, head, nh_hash) {
+		struct fib_info *fi = nh1->nh_parent;
 		int alive;
 
 		BUG_ON(!fi->fib_nhs);
-		if (nh->nh_dev != dev || fi == prev_fi)
+		if (nh1->nh_dev != dev || fi == prev_fi)
 			continue;
 
 		prev_fi = fi;
Signature · 1 line
Stephen Hemminger <[email protected]>