Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: rcu sparse cleanups

Use RCU helpers to reduce number of sparse warnings
(CONFIG_SPARSE_RCU_POINTER=y), and adds lockdep checks.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Eric Dumazet and committed by
Patrick McHardy
c5d277d2 ab0cba25

+26 -9
+12 -3
net/netfilter/nf_conntrack_expect.c
··· 337 337 setup_timer(&exp->timeout, nf_ct_expectation_timed_out, 338 338 (unsigned long)exp); 339 339 if (master_help) { 340 - p = &master_help->helper->expect_policy[exp->class]; 340 + p = &rcu_dereference_protected( 341 + master_help->helper, 342 + lockdep_is_held(&nf_conntrack_lock) 343 + )->expect_policy[exp->class]; 341 344 exp->timeout.expires = jiffies + p->timeout * HZ; 342 345 } 343 346 add_timer(&exp->timeout); ··· 376 373 if (!del_timer(&i->timeout)) 377 374 return 0; 378 375 379 - p = &master_help->helper->expect_policy[i->class]; 376 + p = &rcu_dereference_protected( 377 + master_help->helper, 378 + lockdep_is_held(&nf_conntrack_lock) 379 + )->expect_policy[i->class]; 380 380 i->timeout.expires = jiffies + p->timeout * HZ; 381 381 add_timer(&i->timeout); 382 382 return 1; ··· 417 411 } 418 412 /* Will be over limit? */ 419 413 if (master_help) { 420 - p = &master_help->helper->expect_policy[expect->class]; 414 + p = &rcu_dereference_protected( 415 + master_help->helper, 416 + lockdep_is_held(&nf_conntrack_lock) 417 + )->expect_policy[expect->class]; 421 418 if (p->max_expected && 422 419 master_help->expecting[expect->class] >= p->max_expected) { 423 420 evict_oldest_expect(master, expect);
+4 -2
net/netfilter/nf_conntrack_extend.c
··· 140 140 /* This assumes that extended areas in conntrack for the types 141 141 whose NF_CT_EXT_F_PREALLOC bit set are allocated in order */ 142 142 for (i = min; i <= max; i++) { 143 - t1 = nf_ct_ext_types[i]; 143 + t1 = rcu_dereference_protected(nf_ct_ext_types[i], 144 + lockdep_is_held(&nf_ct_ext_type_mutex)); 144 145 if (!t1) 145 146 continue; 146 147 147 148 t1->alloc_size = ALIGN(sizeof(struct nf_ct_ext), t1->align) + 148 149 t1->len; 149 150 for (j = 0; j < NF_CT_EXT_NUM; j++) { 150 - t2 = nf_ct_ext_types[j]; 151 + t2 = rcu_dereference_protected(nf_ct_ext_types[j], 152 + lockdep_is_held(&nf_ct_ext_type_mutex)); 151 153 if (t2 == NULL || t2 == t1 || 152 154 (t2->flags & NF_CT_EXT_F_PREALLOC) == 0) 153 155 continue;
+8 -2
net/netfilter/nf_conntrack_helper.c
··· 158 158 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); 159 159 struct nf_conn_help *help = nfct_help(ct); 160 160 161 - if (help && help->helper == me) { 161 + if (help && rcu_dereference_protected( 162 + help->helper, 163 + lockdep_is_held(&nf_conntrack_lock) 164 + ) == me) { 162 165 nf_conntrack_event(IPCT_HELPER, ct); 163 166 rcu_assign_pointer(help->helper, NULL); 164 167 } ··· 213 210 hlist_for_each_entry_safe(exp, n, next, 214 211 &net->ct.expect_hash[i], hnode) { 215 212 struct nf_conn_help *help = nfct_help(exp->master); 216 - if ((help->helper == me || exp->helper == me) && 213 + if ((rcu_dereference_protected( 214 + help->helper, 215 + lockdep_is_held(&nf_conntrack_lock) 216 + ) == me || exp->helper == me) && 217 217 del_timer(&exp->timeout)) { 218 218 nf_ct_unlink_expect(exp); 219 219 nf_ct_expect_put(exp);
+2 -2
net/netfilter/nf_conntrack_proto.c
··· 284 284 mutex_lock(&nf_ct_proto_mutex); 285 285 if (!nf_ct_protos[l4proto->l3proto]) { 286 286 /* l3proto may be loaded latter. */ 287 - struct nf_conntrack_l4proto **proto_array; 287 + struct nf_conntrack_l4proto __rcu **proto_array; 288 288 int i; 289 289 290 290 proto_array = kmalloc(MAX_NF_CT_PROTO * ··· 296 296 } 297 297 298 298 for (i = 0; i < MAX_NF_CT_PROTO; i++) 299 - proto_array[i] = &nf_conntrack_l4proto_generic; 299 + RCU_INIT_POINTER(proto_array[i], &nf_conntrack_l4proto_generic); 300 300 301 301 /* Before making proto_array visible to lockless readers, 302 302 * we must make sure its content is committed to memory.