diff options
-rw-r--r-- | include/linux/rculist.h | 17 | ||||
-rw-r--r-- | include/net/sock.h | 4 | ||||
-rw-r--r-- | net/ipv4/udp.c | 4 | ||||
-rw-r--r-- | net/ipv6/udp.c | 4 |
4 files changed, 23 insertions, 6 deletions
diff --git a/include/linux/rculist.h b/include/linux/rculist.h index e649bd3f2c97..3ba2998b22ba 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h | |||
@@ -383,5 +383,22 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, | |||
383 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ | 383 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ |
384 | pos = rcu_dereference(pos->next)) | 384 | pos = rcu_dereference(pos->next)) |
385 | 385 | ||
386 | /** | ||
387 | * hlist_for_each_entry_rcu_safenext - iterate over rcu list of given type | ||
388 | * @tpos: the type * to use as a loop cursor. | ||
389 | * @pos: the &struct hlist_node to use as a loop cursor. | ||
390 | * @head: the head for your list. | ||
391 | * @member: the name of the hlist_node within the struct. | ||
392 | * @next: the &struct hlist_node to use as a next cursor | ||
393 | * | ||
394 | * Special version of hlist_for_each_entry_rcu that make sure | ||
395 | * each next pointer is fetched before each iteration. | ||
396 | */ | ||
397 | #define hlist_for_each_entry_rcu_safenext(tpos, pos, head, member, next) \ | ||
398 | for (pos = rcu_dereference((head)->first); \ | ||
399 | pos && ({ next = pos->next; smp_rmb(); prefetch(next); 1; }) && \ | ||
400 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ | ||
401 | pos = rcu_dereference(next)) | ||
402 | |||
386 | #endif /* __KERNEL__ */ | 403 | #endif /* __KERNEL__ */ |
387 | #endif | 404 | #endif |
diff --git a/include/net/sock.h b/include/net/sock.h index 0bea25db5471..a4f6d3fc0470 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -419,8 +419,8 @@ static __inline__ void sk_add_bind_node(struct sock *sk, | |||
419 | 419 | ||
420 | #define sk_for_each(__sk, node, list) \ | 420 | #define sk_for_each(__sk, node, list) \ |
421 | hlist_for_each_entry(__sk, node, list, sk_node) | 421 | hlist_for_each_entry(__sk, node, list, sk_node) |
422 | #define sk_for_each_rcu(__sk, node, list) \ | 422 | #define sk_for_each_rcu_safenext(__sk, node, list, next) \ |
423 | hlist_for_each_entry_rcu(__sk, node, list, sk_node) | 423 | hlist_for_each_entry_rcu_safenext(__sk, node, list, sk_node, next) |
424 | #define sk_for_each_from(__sk, node) \ | 424 | #define sk_for_each_from(__sk, node) \ |
425 | if (__sk && ({ node = &(__sk)->sk_node; 1; })) \ | 425 | if (__sk && ({ node = &(__sk)->sk_node; 1; })) \ |
426 | hlist_for_each_entry_from(__sk, node, sk_node) | 426 | hlist_for_each_entry_from(__sk, node, sk_node) |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index ced820318f94..c3ecec8a9e1c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -256,7 +256,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
256 | int dif, struct udp_table *udptable) | 256 | int dif, struct udp_table *udptable) |
257 | { | 257 | { |
258 | struct sock *sk, *result; | 258 | struct sock *sk, *result; |
259 | struct hlist_node *node; | 259 | struct hlist_node *node, *next; |
260 | unsigned short hnum = ntohs(dport); | 260 | unsigned short hnum = ntohs(dport); |
261 | unsigned int hash = udp_hashfn(net, hnum); | 261 | unsigned int hash = udp_hashfn(net, hnum); |
262 | struct udp_hslot *hslot = &udptable->hash[hash]; | 262 | struct udp_hslot *hslot = &udptable->hash[hash]; |
@@ -266,7 +266,7 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, | |||
266 | begin: | 266 | begin: |
267 | result = NULL; | 267 | result = NULL; |
268 | badness = -1; | 268 | badness = -1; |
269 | sk_for_each_rcu(sk, node, &hslot->head) { | 269 | sk_for_each_rcu_safenext(sk, node, &hslot->head, next) { |
270 | /* | 270 | /* |
271 | * lockless reader, and SLAB_DESTROY_BY_RCU items: | 271 | * lockless reader, and SLAB_DESTROY_BY_RCU items: |
272 | * We must check this item was not moved to another chain | 272 | * We must check this item was not moved to another chain |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 1d9790e43dfc..32d914db6c4f 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -98,7 +98,7 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
98 | int dif, struct udp_table *udptable) | 98 | int dif, struct udp_table *udptable) |
99 | { | 99 | { |
100 | struct sock *sk, *result; | 100 | struct sock *sk, *result; |
101 | struct hlist_node *node; | 101 | struct hlist_node *node, *next; |
102 | unsigned short hnum = ntohs(dport); | 102 | unsigned short hnum = ntohs(dport); |
103 | unsigned int hash = udp_hashfn(net, hnum); | 103 | unsigned int hash = udp_hashfn(net, hnum); |
104 | struct udp_hslot *hslot = &udptable->hash[hash]; | 104 | struct udp_hslot *hslot = &udptable->hash[hash]; |
@@ -108,7 +108,7 @@ static struct sock *__udp6_lib_lookup(struct net *net, | |||
108 | begin: | 108 | begin: |
109 | result = NULL; | 109 | result = NULL; |
110 | badness = -1; | 110 | badness = -1; |
111 | sk_for_each_rcu(sk, node, &hslot->head) { | 111 | sk_for_each_rcu_safenext(sk, node, &hslot->head, next) { |
112 | /* | 112 | /* |
113 | * lockless reader, and SLAB_DESTROY_BY_RCU items: | 113 | * lockless reader, and SLAB_DESTROY_BY_RCU items: |
114 | * We must check this item was not moved to another chain | 114 | * We must check this item was not moved to another chain |