Messages in this thread Patch in this message | | | Subject | Re: [PATCH] ipv4: fix a RCU-list lock in fib_triestat_seq_show | From | Eric Dumazet <> | Date | Wed, 25 Mar 2020 09:13:52 -0700 |
| |
On 3/25/20 8:55 AM, Qian Cai wrote: > fib_triestat_seq_show() calls hlist_for_each_entry_rcu(tb, head, > tb_hlist) without rcu_read_lock() will trigger a warning, > > net/ipv4/fib_trie.c:2579 RCU-list traversed in non-reader section!! > > other info that might help us debug this: > > rcu_scheduler_active = 2, debug_locks = 1 > 1 lock held by proc01/115277: > #0: c0000014507acf00 (&p->lock){+.+.}-{3:3}, at: seq_read+0x58/0x670 > > Call Trace: > dump_stack+0xf4/0x164 (unreliable) > lockdep_rcu_suspicious+0x140/0x164 > fib_triestat_seq_show+0x750/0x880 > seq_read+0x1a0/0x670 > proc_reg_read+0x10c/0x1b0 > __vfs_read+0x3c/0x70 > vfs_read+0xac/0x170 > ksys_read+0x7c/0x140 > system_call+0x5c/0x68 > > Signed-off-by: Qian Cai <cai@lca.pw> > --- > net/ipv4/fib_trie.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c > index ff0c24371e33..73fa37476f03 100644 > --- a/net/ipv4/fib_trie.c > +++ b/net/ipv4/fib_trie.c > @@ -2577,6 +2577,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, void *v) > " %zd bytes, size of tnode: %zd bytes.\n", > LEAF_SIZE, TNODE_SIZE(0)); > > + rcu_read_lock(); > for (h = 0; h < FIB_TABLE_HASHSZ; h++) { > struct hlist_head *head = &net->ipv4.fib_table_hash[h]; > struct fib_table *tb; > @@ -2597,6 +2598,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, void *v) > #endif > } > } > + rcu_read_unlock(); > > return 0; > } >
We probably want to be able to reschedule in the loop (adding a cond_resched() in net-next)
I would prefer :
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index ff0c24371e3309b3068980f46d1ed743337d2a3e..4b98ffb27136d3b43f179d6b1b42fe84586acc06 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -2581,6 +2581,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, void *v) struct hlist_head *head = &net->ipv4.fib_table_hash[h]; struct fib_table *tb; + rcu_read_lock(); hlist_for_each_entry_rcu(tb, head, tb_hlist) { struct trie *t = (struct trie *) tb->tb_data; struct trie_stat stat; @@ -2596,6 +2597,7 @@ static int fib_triestat_seq_show(struct seq_file *seq, void *v) trie_show_usage(seq, t->stats); #endif } + rcu_read_unlock(); } return 0;
| |