aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2015-01-02 17:00:16 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-03 14:32:56 -0500
commit88d6ed15acff1cb44b1d1f3c0a393b7f7744957a (patch)
treeee25a48f8ab11d06c062480c89ba1e96c8113e57
parenta4b18cda4c2676a4b4b59622b2e0394dc153e00b (diff)
rhashtable: Convert bucket iterators to take table and index
This patch is in preparation to introduce per bucket spinlocks. It extends all iterator macros to take the bucket table and bucket index. It also introduces a new rht_dereference_bucket() to handle protected accesses to buckets. It introduces a barrier() to the RCU iterators to the prevent the compiler from caching the first element. The lockdep verifier is introduced as stub which always succeeds and properly implement in the next patch when the locks are introduced. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/rhashtable.h173
-rw-r--r--lib/rhashtable.c30
-rw-r--r--net/netfilter/nft_hash.c12
-rw-r--r--net/netlink/af_netlink.c12
-rw-r--r--net/netlink/diag.c4
5 files changed, 152 insertions, 79 deletions
diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h
index 1b51221c6bbd..b54e24a08806 100644
--- a/include/linux/rhashtable.h
+++ b/include/linux/rhashtable.h
@@ -87,11 +87,18 @@ struct rhashtable {
87 87
88#ifdef CONFIG_PROVE_LOCKING 88#ifdef CONFIG_PROVE_LOCKING
89int lockdep_rht_mutex_is_held(const struct rhashtable *ht); 89int lockdep_rht_mutex_is_held(const struct rhashtable *ht);
90int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash);
90#else 91#else
91static inline int lockdep_rht_mutex_is_held(const struct rhashtable *ht) 92static inline int lockdep_rht_mutex_is_held(const struct rhashtable *ht)
92{ 93{
93 return 1; 94 return 1;
94} 95}
96
97static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl,
98 u32 hash)
99{
100 return 1;
101}
95#endif /* CONFIG_PROVE_LOCKING */ 102#endif /* CONFIG_PROVE_LOCKING */
96 103
97int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params); 104int rhashtable_init(struct rhashtable *ht, struct rhashtable_params *params);
@@ -119,92 +126,144 @@ void rhashtable_destroy(const struct rhashtable *ht);
119#define rht_dereference_rcu(p, ht) \ 126#define rht_dereference_rcu(p, ht) \
120 rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht)) 127 rcu_dereference_check(p, lockdep_rht_mutex_is_held(ht))
121 128
122#define rht_entry(ptr, type, member) container_of(ptr, type, member) 129#define rht_dereference_bucket(p, tbl, hash) \
123#define rht_entry_safe(ptr, type, member) \ 130 rcu_dereference_protected(p, lockdep_rht_bucket_is_held(tbl, hash))
124({ \
125 typeof(ptr) __ptr = (ptr); \
126 __ptr ? rht_entry(__ptr, type, member) : NULL; \
127})
128 131
129#define rht_next_entry_safe(pos, ht, member) \ 132#define rht_dereference_bucket_rcu(p, tbl, hash) \
130({ \ 133 rcu_dereference_check(p, lockdep_rht_bucket_is_held(tbl, hash))
131 pos ? rht_entry_safe(rht_dereference((pos)->member.next, ht), \ 134
132 typeof(*(pos)), member) : NULL; \ 135#define rht_entry(tpos, pos, member) \
133}) 136 ({ tpos = container_of(pos, typeof(*tpos), member); 1; })
134 137
135/** 138/**
136 * rht_for_each - iterate over hash chain 139 * rht_for_each_continue - continue iterating over hash chain
137 * @pos: &struct rhash_head to use as a loop cursor. 140 * @pos: the &struct rhash_head to use as a loop cursor.
138 * @head: head of the hash chain (struct rhash_head *) 141 * @head: the previous &struct rhash_head to continue from
139 * @ht: pointer to your struct rhashtable 142 * @tbl: the &struct bucket_table
143 * @hash: the hash value / bucket index
140 */ 144 */
141#define rht_for_each(pos, head, ht) \ 145#define rht_for_each_continue(pos, head, tbl, hash) \
142 for (pos = rht_dereference(head, ht); \ 146 for (pos = rht_dereference_bucket(head, tbl, hash); \
143 pos; \ 147 pos; \
144 pos = rht_dereference((pos)->next, ht)) 148 pos = rht_dereference_bucket((pos)->next, tbl, hash))
149
150/**
151 * rht_for_each - iterate over hash chain
152 * @pos: the &struct rhash_head to use as a loop cursor.
153 * @tbl: the &struct bucket_table
154 * @hash: the hash value / bucket index
155 */
156#define rht_for_each(pos, tbl, hash) \
157 rht_for_each_continue(pos, (tbl)->buckets[hash], tbl, hash)
158
159/**
160 * rht_for_each_entry_continue - continue iterating over hash chain
161 * @tpos: the type * to use as a loop cursor.
162 * @pos: the &struct rhash_head to use as a loop cursor.
163 * @head: the previous &struct rhash_head to continue from
164 * @tbl: the &struct bucket_table
165 * @hash: the hash value / bucket index
166 * @member: name of the &struct rhash_head within the hashable struct.
167 */
168#define rht_for_each_entry_continue(tpos, pos, head, tbl, hash, member) \
169 for (pos = rht_dereference_bucket(head, tbl, hash); \
170 pos && rht_entry(tpos, pos, member); \
171 pos = rht_dereference_bucket((pos)->next, tbl, hash))
145 172
146/** 173/**
147 * rht_for_each_entry - iterate over hash chain of given type 174 * rht_for_each_entry - iterate over hash chain of given type
148 * @pos: type * to use as a loop cursor. 175 * @tpos: the type * to use as a loop cursor.
149 * @head: head of the hash chain (struct rhash_head *) 176 * @pos: the &struct rhash_head to use as a loop cursor.
150 * @ht: pointer to your struct rhashtable 177 * @tbl: the &struct bucket_table
151 * @member: name of the rhash_head within the hashable struct. 178 * @hash: the hash value / bucket index
179 * @member: name of the &struct rhash_head within the hashable struct.
152 */ 180 */
153#define rht_for_each_entry(pos, head, ht, member) \ 181#define rht_for_each_entry(tpos, pos, tbl, hash, member) \
154 for (pos = rht_entry_safe(rht_dereference(head, ht), \ 182 rht_for_each_entry_continue(tpos, pos, (tbl)->buckets[hash], \
155 typeof(*(pos)), member); \ 183 tbl, hash, member)
156 pos; \
157 pos = rht_next_entry_safe(pos, ht, member))
158 184
159/** 185/**
160 * rht_for_each_entry_safe - safely iterate over hash chain of given type 186 * rht_for_each_entry_safe - safely iterate over hash chain of given type
161 * @pos: type * to use as a loop cursor. 187 * @tpos: the type * to use as a loop cursor.
162 * @n: type * to use for temporary next object storage 188 * @pos: the &struct rhash_head to use as a loop cursor.
163 * @head: head of the hash chain (struct rhash_head *) 189 * @next: the &struct rhash_head to use as next in loop cursor.
164 * @ht: pointer to your struct rhashtable 190 * @tbl: the &struct bucket_table
165 * @member: name of the rhash_head within the hashable struct. 191 * @hash: the hash value / bucket index
192 * @member: name of the &struct rhash_head within the hashable struct.
166 * 193 *
167 * This hash chain list-traversal primitive allows for the looped code to 194 * This hash chain list-traversal primitive allows for the looped code to
168 * remove the loop cursor from the list. 195 * remove the loop cursor from the list.
169 */ 196 */
170#define rht_for_each_entry_safe(pos, n, head, ht, member) \ 197#define rht_for_each_entry_safe(tpos, pos, next, tbl, hash, member) \
171 for (pos = rht_entry_safe(rht_dereference(head, ht), \ 198 for (pos = rht_dereference_bucket((tbl)->buckets[hash], tbl, hash), \
172 typeof(*(pos)), member), \ 199 next = pos ? rht_dereference_bucket(pos->next, tbl, hash) \
173 n = rht_next_entry_safe(pos, ht, member); \ 200 : NULL; \
174 pos; \ 201 pos && rht_entry(tpos, pos, member); \
175 pos = n, \ 202 pos = next)
176 n = rht_next_entry_safe(pos, ht, member)) 203
204/**
205 * rht_for_each_rcu_continue - continue iterating over rcu hash chain
206 * @pos: the &struct rhash_head to use as a loop cursor.
207 * @head: the previous &struct rhash_head to continue from
208 * @tbl: the &struct bucket_table
209 * @hash: the hash value / bucket index
210 *
211 * This hash chain list-traversal primitive may safely run concurrently with
212 * the _rcu mutation primitives such as rhashtable_insert() as long as the
213 * traversal is guarded by rcu_read_lock().
214 */
215#define rht_for_each_rcu_continue(pos, head, tbl, hash) \
216 for (({barrier(); }), \
217 pos = rht_dereference_bucket_rcu(head, tbl, hash); \
218 pos; \
219 pos = rcu_dereference_raw(pos->next))
177 220
178/** 221/**
179 * rht_for_each_rcu - iterate over rcu hash chain 222 * rht_for_each_rcu - iterate over rcu hash chain
180 * @pos: &struct rhash_head to use as a loop cursor. 223 * @pos: the &struct rhash_head to use as a loop cursor.
181 * @head: head of the hash chain (struct rhash_head *) 224 * @tbl: the &struct bucket_table
182 * @ht: pointer to your struct rhashtable 225 * @hash: the hash value / bucket index
183 * 226 *
184 * This hash chain list-traversal primitive may safely run concurrently with 227 * This hash chain list-traversal primitive may safely run concurrently with
185 * the _rcu fkht mutation primitives such as rht_insert() as long as the 228 * the _rcu mutation primitives such as rhashtable_insert() as long as the
186 * traversal is guarded by rcu_read_lock(). 229 * traversal is guarded by rcu_read_lock().
187 */ 230 */
188#define rht_for_each_rcu(pos, head, ht) \ 231#define rht_for_each_rcu(pos, tbl, hash) \
189 for (pos = rht_dereference_rcu(head, ht); \ 232 rht_for_each_rcu_continue(pos, (tbl)->buckets[hash], tbl, hash)
190 pos; \ 233
191 pos = rht_dereference_rcu((pos)->next, ht)) 234/**
235 * rht_for_each_entry_rcu_continue - continue iterating over rcu hash chain
236 * @tpos: the type * to use as a loop cursor.
237 * @pos: the &struct rhash_head to use as a loop cursor.
238 * @head: the previous &struct rhash_head to continue from
239 * @tbl: the &struct bucket_table
240 * @hash: the hash value / bucket index
241 * @member: name of the &struct rhash_head within the hashable struct.
242 *
243 * This hash chain list-traversal primitive may safely run concurrently with
244 * the _rcu mutation primitives such as rhashtable_insert() as long as the
245 * traversal is guarded by rcu_read_lock().
246 */
247#define rht_for_each_entry_rcu_continue(tpos, pos, head, tbl, hash, member) \
248 for (({barrier(); }), \
249 pos = rht_dereference_bucket_rcu(head, tbl, hash); \
250 pos && rht_entry(tpos, pos, member); \
251 pos = rht_dereference_bucket_rcu(pos->next, tbl, hash))
192 252
193/** 253/**
194 * rht_for_each_entry_rcu - iterate over rcu hash chain of given type 254 * rht_for_each_entry_rcu - iterate over rcu hash chain of given type
195 * @pos: type * to use as a loop cursor. 255 * @tpos: the type * to use as a loop cursor.
196 * @head: head of the hash chain (struct rhash_head *) 256 * @pos: the &struct rhash_head to use as a loop cursor.
197 * @member: name of the rhash_head within the hashable struct. 257 * @tbl: the &struct bucket_table
258 * @hash: the hash value / bucket index
259 * @member: name of the &struct rhash_head within the hashable struct.
198 * 260 *
199 * This hash chain list-traversal primitive may safely run concurrently with 261 * This hash chain list-traversal primitive may safely run concurrently with
200 * the _rcu fkht mutation primitives such as rht_insert() as long as the 262 * the _rcu mutation primitives such as rhashtable_insert() as long as the
201 * traversal is guarded by rcu_read_lock(). 263 * traversal is guarded by rcu_read_lock().
202 */ 264 */
203#define rht_for_each_entry_rcu(pos, head, member) \ 265#define rht_for_each_entry_rcu(tpos, pos, tbl, hash, member) \
204 for (pos = rht_entry_safe(rcu_dereference_raw(head), \ 266 rht_for_each_entry_rcu_continue(tpos, pos, (tbl)->buckets[hash],\
205 typeof(*(pos)), member); \ 267 tbl, hash, member)
206 pos; \
207 pos = rht_entry_safe(rcu_dereference_raw((pos)->member.next), \
208 typeof(*(pos)), member))
209 268
210#endif /* _LINUX_RHASHTABLE_H */ 269#endif /* _LINUX_RHASHTABLE_H */
diff --git a/lib/rhashtable.c b/lib/rhashtable.c
index b658245826a1..ce450d095fdf 100644
--- a/lib/rhashtable.c
+++ b/lib/rhashtable.c
@@ -35,6 +35,12 @@ int lockdep_rht_mutex_is_held(const struct rhashtable *ht)
35 return ht->p.mutex_is_held(ht->p.parent); 35 return ht->p.mutex_is_held(ht->p.parent);
36} 36}
37EXPORT_SYMBOL_GPL(lockdep_rht_mutex_is_held); 37EXPORT_SYMBOL_GPL(lockdep_rht_mutex_is_held);
38
39int lockdep_rht_bucket_is_held(const struct bucket_table *tbl, u32 hash)
40{
41 return 1;
42}
43EXPORT_SYMBOL_GPL(lockdep_rht_bucket_is_held);
38#endif 44#endif
39 45
40static void *rht_obj(const struct rhashtable *ht, const struct rhash_head *he) 46static void *rht_obj(const struct rhashtable *ht, const struct rhash_head *he)
@@ -141,7 +147,7 @@ static void hashtable_chain_unzip(const struct rhashtable *ht,
141 * previous node p. Call the previous node p; 147 * previous node p. Call the previous node p;
142 */ 148 */
143 h = head_hashfn(ht, new_tbl, p); 149 h = head_hashfn(ht, new_tbl, p);
144 rht_for_each(he, p->next, ht) { 150 rht_for_each_continue(he, p->next, old_tbl, n) {
145 if (head_hashfn(ht, new_tbl, he) != h) 151 if (head_hashfn(ht, new_tbl, he) != h)
146 break; 152 break;
147 p = he; 153 p = he;
@@ -153,7 +159,7 @@ static void hashtable_chain_unzip(const struct rhashtable *ht,
153 */ 159 */
154 next = NULL; 160 next = NULL;
155 if (he) { 161 if (he) {
156 rht_for_each(he, he->next, ht) { 162 rht_for_each_continue(he, he->next, old_tbl, n) {
157 if (head_hashfn(ht, new_tbl, he) == h) { 163 if (head_hashfn(ht, new_tbl, he) == h) {
158 next = he; 164 next = he;
159 break; 165 break;
@@ -208,7 +214,7 @@ int rhashtable_expand(struct rhashtable *ht)
208 */ 214 */
209 for (i = 0; i < new_tbl->size; i++) { 215 for (i = 0; i < new_tbl->size; i++) {
210 h = rht_bucket_index(old_tbl, i); 216 h = rht_bucket_index(old_tbl, i);
211 rht_for_each(he, old_tbl->buckets[h], ht) { 217 rht_for_each(he, old_tbl, h) {
212 if (head_hashfn(ht, new_tbl, he) == i) { 218 if (head_hashfn(ht, new_tbl, he) == i) {
213 RCU_INIT_POINTER(new_tbl->buckets[i], he); 219 RCU_INIT_POINTER(new_tbl->buckets[i], he);
214 break; 220 break;
@@ -286,7 +292,7 @@ int rhashtable_shrink(struct rhashtable *ht)
286 * to the new bucket. 292 * to the new bucket.
287 */ 293 */
288 for (pprev = &ntbl->buckets[i]; *pprev != NULL; 294 for (pprev = &ntbl->buckets[i]; *pprev != NULL;
289 pprev = &rht_dereference(*pprev, ht)->next) 295 pprev = &rht_dereference_bucket(*pprev, ntbl, i)->next)
290 ; 296 ;
291 RCU_INIT_POINTER(*pprev, tbl->buckets[i + ntbl->size]); 297 RCU_INIT_POINTER(*pprev, tbl->buckets[i + ntbl->size]);
292 } 298 }
@@ -386,7 +392,7 @@ bool rhashtable_remove(struct rhashtable *ht, struct rhash_head *obj)
386 h = head_hashfn(ht, tbl, obj); 392 h = head_hashfn(ht, tbl, obj);
387 393
388 pprev = &tbl->buckets[h]; 394 pprev = &tbl->buckets[h];
389 rht_for_each(he, tbl->buckets[h], ht) { 395 rht_for_each(he, tbl, h) {
390 if (he != obj) { 396 if (he != obj) {
391 pprev = &he->next; 397 pprev = &he->next;
392 continue; 398 continue;
@@ -423,7 +429,7 @@ void *rhashtable_lookup(const struct rhashtable *ht, const void *key)
423 BUG_ON(!ht->p.key_len); 429 BUG_ON(!ht->p.key_len);
424 430
425 h = key_hashfn(ht, key, ht->p.key_len); 431 h = key_hashfn(ht, key, ht->p.key_len);
426 rht_for_each_rcu(he, tbl->buckets[h], ht) { 432 rht_for_each_rcu(he, tbl, h) {
427 if (memcmp(rht_obj(ht, he) + ht->p.key_offset, key, 433 if (memcmp(rht_obj(ht, he) + ht->p.key_offset, key,
428 ht->p.key_len)) 434 ht->p.key_len))
429 continue; 435 continue;
@@ -457,7 +463,7 @@ void *rhashtable_lookup_compare(const struct rhashtable *ht, const void *key,
457 u32 hash; 463 u32 hash;
458 464
459 hash = key_hashfn(ht, key, ht->p.key_len); 465 hash = key_hashfn(ht, key, ht->p.key_len);
460 rht_for_each_rcu(he, tbl->buckets[hash], ht) { 466 rht_for_each_rcu(he, tbl, hash) {
461 if (!compare(rht_obj(ht, he), arg)) 467 if (!compare(rht_obj(ht, he), arg))
462 continue; 468 continue;
463 return rht_obj(ht, he); 469 return rht_obj(ht, he);
@@ -625,6 +631,7 @@ static int __init test_rht_lookup(struct rhashtable *ht)
625static void test_bucket_stats(struct rhashtable *ht, bool quiet) 631static void test_bucket_stats(struct rhashtable *ht, bool quiet)
626{ 632{
627 unsigned int cnt, rcu_cnt, i, total = 0; 633 unsigned int cnt, rcu_cnt, i, total = 0;
634 struct rhash_head *pos;
628 struct test_obj *obj; 635 struct test_obj *obj;
629 struct bucket_table *tbl; 636 struct bucket_table *tbl;
630 637
@@ -635,14 +642,14 @@ static void test_bucket_stats(struct rhashtable *ht, bool quiet)
635 if (!quiet) 642 if (!quiet)
636 pr_info(" [%#4x/%zu]", i, tbl->size); 643 pr_info(" [%#4x/%zu]", i, tbl->size);
637 644
638 rht_for_each_entry_rcu(obj, tbl->buckets[i], node) { 645 rht_for_each_entry_rcu(obj, pos, tbl, i, node) {
639 cnt++; 646 cnt++;
640 total++; 647 total++;
641 if (!quiet) 648 if (!quiet)
642 pr_cont(" [%p],", obj); 649 pr_cont(" [%p],", obj);
643 } 650 }
644 651
645 rht_for_each_entry_rcu(obj, tbl->buckets[i], node) 652 rht_for_each_entry_rcu(obj, pos, tbl, i, node)
646 rcu_cnt++; 653 rcu_cnt++;
647 654
648 if (rcu_cnt != cnt) 655 if (rcu_cnt != cnt)
@@ -664,7 +671,8 @@ static void test_bucket_stats(struct rhashtable *ht, bool quiet)
664static int __init test_rhashtable(struct rhashtable *ht) 671static int __init test_rhashtable(struct rhashtable *ht)
665{ 672{
666 struct bucket_table *tbl; 673 struct bucket_table *tbl;
667 struct test_obj *obj, *next; 674 struct test_obj *obj;
675 struct rhash_head *pos, *next;
668 int err; 676 int err;
669 unsigned int i; 677 unsigned int i;
670 678
@@ -733,7 +741,7 @@ static int __init test_rhashtable(struct rhashtable *ht)
733error: 741error:
734 tbl = rht_dereference_rcu(ht->tbl, ht); 742 tbl = rht_dereference_rcu(ht->tbl, ht);
735 for (i = 0; i < tbl->size; i++) 743 for (i = 0; i < tbl->size; i++)
736 rht_for_each_entry_safe(obj, next, tbl->buckets[i], ht, node) 744 rht_for_each_entry_safe(obj, pos, next, tbl, i, node)
737 kfree(obj); 745 kfree(obj);
738 746
739 return err; 747 return err;
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 614ee099ba36..d93f1f4c22a9 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -142,7 +142,9 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
142 142
143 tbl = rht_dereference_rcu(priv->tbl, priv); 143 tbl = rht_dereference_rcu(priv->tbl, priv);
144 for (i = 0; i < tbl->size; i++) { 144 for (i = 0; i < tbl->size; i++) {
145 rht_for_each_entry_rcu(he, tbl->buckets[i], node) { 145 struct rhash_head *pos;
146
147 rht_for_each_entry_rcu(he, pos, tbl, i, node) {
146 if (iter->count < iter->skip) 148 if (iter->count < iter->skip)
147 goto cont; 149 goto cont;
148 150
@@ -197,15 +199,13 @@ static void nft_hash_destroy(const struct nft_set *set)
197{ 199{
198 const struct rhashtable *priv = nft_set_priv(set); 200 const struct rhashtable *priv = nft_set_priv(set);
199 const struct bucket_table *tbl = priv->tbl; 201 const struct bucket_table *tbl = priv->tbl;
200 struct nft_hash_elem *he, *next; 202 struct nft_hash_elem *he;
203 struct rhash_head *pos, *next;
201 unsigned int i; 204 unsigned int i;
202 205
203 for (i = 0; i < tbl->size; i++) { 206 for (i = 0; i < tbl->size; i++) {
204 for (he = rht_entry(tbl->buckets[i], struct nft_hash_elem, node); 207 rht_for_each_entry_safe(he, pos, next, tbl, i, node)
205 he != NULL; he = next) {
206 next = rht_entry(he->node.next, struct nft_hash_elem, node);
207 nft_hash_elem_destroy(set, he); 208 nft_hash_elem_destroy(set, he);
208 }
209 } 209 }
210 rhashtable_destroy(priv); 210 rhashtable_destroy(priv);
211} 211}
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a5d7ed627563..57449b6089c2 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2898,7 +2898,9 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos)
2898 const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); 2898 const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
2899 2899
2900 for (j = 0; j < tbl->size; j++) { 2900 for (j = 0; j < tbl->size; j++) {
2901 rht_for_each_entry_rcu(nlk, tbl->buckets[j], node) { 2901 struct rhash_head *node;
2902
2903 rht_for_each_entry_rcu(nlk, node, tbl, j, node) {
2902 s = (struct sock *)nlk; 2904 s = (struct sock *)nlk;
2903 2905
2904 if (sock_net(s) != seq_file_net(seq)) 2906 if (sock_net(s) != seq_file_net(seq))
@@ -2926,6 +2928,8 @@ static void *netlink_seq_start(struct seq_file *seq, loff_t *pos)
2926static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) 2928static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2927{ 2929{
2928 struct rhashtable *ht; 2930 struct rhashtable *ht;
2931 const struct bucket_table *tbl;
2932 struct rhash_head *node;
2929 struct netlink_sock *nlk; 2933 struct netlink_sock *nlk;
2930 struct nl_seq_iter *iter; 2934 struct nl_seq_iter *iter;
2931 struct net *net; 2935 struct net *net;
@@ -2942,17 +2946,17 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2942 2946
2943 i = iter->link; 2947 i = iter->link;
2944 ht = &nl_table[i].hash; 2948 ht = &nl_table[i].hash;
2945 rht_for_each_entry(nlk, nlk->node.next, ht, node) 2949 tbl = rht_dereference_rcu(ht->tbl, ht);
2950 rht_for_each_entry_rcu_continue(nlk, node, nlk->node.next, tbl, iter->hash_idx, node)
2946 if (net_eq(sock_net((struct sock *)nlk), net)) 2951 if (net_eq(sock_net((struct sock *)nlk), net))
2947 return nlk; 2952 return nlk;
2948 2953
2949 j = iter->hash_idx + 1; 2954 j = iter->hash_idx + 1;
2950 2955
2951 do { 2956 do {
2952 const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht);
2953 2957
2954 for (; j < tbl->size; j++) { 2958 for (; j < tbl->size; j++) {
2955 rht_for_each_entry(nlk, tbl->buckets[j], ht, node) { 2959 rht_for_each_entry_rcu(nlk, node, tbl, j, node) {
2956 if (net_eq(sock_net((struct sock *)nlk), net)) { 2960 if (net_eq(sock_net((struct sock *)nlk), net)) {
2957 iter->link = i; 2961 iter->link = i;
2958 iter->hash_idx = j; 2962 iter->hash_idx = j;
diff --git a/net/netlink/diag.c b/net/netlink/diag.c
index de8c74a3c061..fcca36d81a62 100644
--- a/net/netlink/diag.c
+++ b/net/netlink/diag.c
@@ -113,7 +113,9 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
113 req = nlmsg_data(cb->nlh); 113 req = nlmsg_data(cb->nlh);
114 114
115 for (i = 0; i < htbl->size; i++) { 115 for (i = 0; i < htbl->size; i++) {
116 rht_for_each_entry(nlsk, htbl->buckets[i], ht, node) { 116 struct rhash_head *pos;
117
118 rht_for_each_entry(nlsk, pos, htbl, i, node) {
117 sk = (struct sock *)nlsk; 119 sk = (struct sock *)nlsk;
118 120
119 if (!net_eq(sock_net(sk), net)) 121 if (!net_eq(sock_net(sk), net))