diff options
author | Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp> | 2005-11-16 15:55:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-11-16 15:55:37 -0500 |
commit | e7c8a41e817f381ac5c2a59ecc81b483bd68a7df (patch) | |
tree | 650b33c804a1a66c72acaef9595eb9fe6cc2c0e9 /net | |
parent | 0db169f9703115bab09eda5d89a8f6937a7bf98e (diff) |
[IPV4,IPV6]: replace handmade list with hlist in IPv{4,6} reassembly
Both of ipq and frag_queue have *next and **prev, and they can be replaced
with hlist. Thanks Arnaldo Carvalho de Melo for the suggestion.
Signed-off-by: Yasuyuki Kozakai <yasuyuki.kozakai@toshiba.co.jp>
Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/ip_fragment.c | 40 | ||||
-rw-r--r-- | net/ipv6/reassembly.c | 41 |
2 files changed, 30 insertions, 51 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index e7d26d9943c2..8ce0ce2ee48e 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -71,7 +71,7 @@ struct ipfrag_skb_cb | |||
71 | 71 | ||
72 | /* Describe an entry in the "incomplete datagrams" queue. */ | 72 | /* Describe an entry in the "incomplete datagrams" queue. */ |
73 | struct ipq { | 73 | struct ipq { |
74 | struct ipq *next; /* linked list pointers */ | 74 | struct hlist_node list; |
75 | struct list_head lru_list; /* lru list member */ | 75 | struct list_head lru_list; /* lru list member */ |
76 | u32 user; | 76 | u32 user; |
77 | u32 saddr; | 77 | u32 saddr; |
@@ -89,7 +89,6 @@ struct ipq { | |||
89 | spinlock_t lock; | 89 | spinlock_t lock; |
90 | atomic_t refcnt; | 90 | atomic_t refcnt; |
91 | struct timer_list timer; /* when will this queue expire? */ | 91 | struct timer_list timer; /* when will this queue expire? */ |
92 | struct ipq **pprev; | ||
93 | int iif; | 92 | int iif; |
94 | struct timeval stamp; | 93 | struct timeval stamp; |
95 | }; | 94 | }; |
@@ -99,7 +98,7 @@ struct ipq { | |||
99 | #define IPQ_HASHSZ 64 | 98 | #define IPQ_HASHSZ 64 |
100 | 99 | ||
101 | /* Per-bucket lock is easy to add now. */ | 100 | /* Per-bucket lock is easy to add now. */ |
102 | static struct ipq *ipq_hash[IPQ_HASHSZ]; | 101 | static struct hlist_head ipq_hash[IPQ_HASHSZ]; |
103 | static DEFINE_RWLOCK(ipfrag_lock); | 102 | static DEFINE_RWLOCK(ipfrag_lock); |
104 | static u32 ipfrag_hash_rnd; | 103 | static u32 ipfrag_hash_rnd; |
105 | static LIST_HEAD(ipq_lru_list); | 104 | static LIST_HEAD(ipq_lru_list); |
@@ -107,9 +106,7 @@ int ip_frag_nqueues = 0; | |||
107 | 106 | ||
108 | static __inline__ void __ipq_unlink(struct ipq *qp) | 107 | static __inline__ void __ipq_unlink(struct ipq *qp) |
109 | { | 108 | { |
110 | if(qp->next) | 109 | hlist_del(&qp->list); |
111 | qp->next->pprev = qp->pprev; | ||
112 | *qp->pprev = qp->next; | ||
113 | list_del(&qp->lru_list); | 110 | list_del(&qp->lru_list); |
114 | ip_frag_nqueues--; | 111 | ip_frag_nqueues--; |
115 | } | 112 | } |
@@ -139,27 +136,18 @@ static void ipfrag_secret_rebuild(unsigned long dummy) | |||
139 | get_random_bytes(&ipfrag_hash_rnd, sizeof(u32)); | 136 | get_random_bytes(&ipfrag_hash_rnd, sizeof(u32)); |
140 | for (i = 0; i < IPQ_HASHSZ; i++) { | 137 | for (i = 0; i < IPQ_HASHSZ; i++) { |
141 | struct ipq *q; | 138 | struct ipq *q; |
139 | struct hlist_node *p, *n; | ||
142 | 140 | ||
143 | q = ipq_hash[i]; | 141 | hlist_for_each_entry_safe(q, p, n, &ipq_hash[i], list) { |
144 | while (q) { | ||
145 | struct ipq *next = q->next; | ||
146 | unsigned int hval = ipqhashfn(q->id, q->saddr, | 142 | unsigned int hval = ipqhashfn(q->id, q->saddr, |
147 | q->daddr, q->protocol); | 143 | q->daddr, q->protocol); |
148 | 144 | ||
149 | if (hval != i) { | 145 | if (hval != i) { |
150 | /* Unlink. */ | 146 | hlist_del(&q->list); |
151 | if (q->next) | ||
152 | q->next->pprev = q->pprev; | ||
153 | *q->pprev = q->next; | ||
154 | 147 | ||
155 | /* Relink to new hash chain. */ | 148 | /* Relink to new hash chain. */ |
156 | if ((q->next = ipq_hash[hval]) != NULL) | 149 | hlist_add_head(&q->list, &ipq_hash[hval]); |
157 | q->next->pprev = &q->next; | ||
158 | ipq_hash[hval] = q; | ||
159 | q->pprev = &ipq_hash[hval]; | ||
160 | } | 150 | } |
161 | |||
162 | q = next; | ||
163 | } | 151 | } |
164 | } | 152 | } |
165 | write_unlock(&ipfrag_lock); | 153 | write_unlock(&ipfrag_lock); |
@@ -310,14 +298,16 @@ out: | |||
310 | static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) | 298 | static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) |
311 | { | 299 | { |
312 | struct ipq *qp; | 300 | struct ipq *qp; |
313 | 301 | #ifdef CONFIG_SMP | |
302 | struct hlist_node *n; | ||
303 | #endif | ||
314 | write_lock(&ipfrag_lock); | 304 | write_lock(&ipfrag_lock); |
315 | #ifdef CONFIG_SMP | 305 | #ifdef CONFIG_SMP |
316 | /* With SMP race we have to recheck hash table, because | 306 | /* With SMP race we have to recheck hash table, because |
317 | * such entry could be created on other cpu, while we | 307 | * such entry could be created on other cpu, while we |
318 | * promoted read lock to write lock. | 308 | * promoted read lock to write lock. |
319 | */ | 309 | */ |
320 | for(qp = ipq_hash[hash]; qp; qp = qp->next) { | 310 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { |
321 | if(qp->id == qp_in->id && | 311 | if(qp->id == qp_in->id && |
322 | qp->saddr == qp_in->saddr && | 312 | qp->saddr == qp_in->saddr && |
323 | qp->daddr == qp_in->daddr && | 313 | qp->daddr == qp_in->daddr && |
@@ -337,10 +327,7 @@ static struct ipq *ip_frag_intern(unsigned int hash, struct ipq *qp_in) | |||
337 | atomic_inc(&qp->refcnt); | 327 | atomic_inc(&qp->refcnt); |
338 | 328 | ||
339 | atomic_inc(&qp->refcnt); | 329 | atomic_inc(&qp->refcnt); |
340 | if((qp->next = ipq_hash[hash]) != NULL) | 330 | hlist_add_head(&qp->list, &ipq_hash[hash]); |
341 | qp->next->pprev = &qp->next; | ||
342 | ipq_hash[hash] = qp; | ||
343 | qp->pprev = &ipq_hash[hash]; | ||
344 | INIT_LIST_HEAD(&qp->lru_list); | 331 | INIT_LIST_HEAD(&qp->lru_list); |
345 | list_add_tail(&qp->lru_list, &ipq_lru_list); | 332 | list_add_tail(&qp->lru_list, &ipq_lru_list); |
346 | ip_frag_nqueues++; | 333 | ip_frag_nqueues++; |
@@ -392,9 +379,10 @@ static inline struct ipq *ip_find(struct iphdr *iph, u32 user) | |||
392 | __u8 protocol = iph->protocol; | 379 | __u8 protocol = iph->protocol; |
393 | unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); | 380 | unsigned int hash = ipqhashfn(id, saddr, daddr, protocol); |
394 | struct ipq *qp; | 381 | struct ipq *qp; |
382 | struct hlist_node *n; | ||
395 | 383 | ||
396 | read_lock(&ipfrag_lock); | 384 | read_lock(&ipfrag_lock); |
397 | for(qp = ipq_hash[hash]; qp; qp = qp->next) { | 385 | hlist_for_each_entry(qp, n, &ipq_hash[hash], list) { |
398 | if(qp->id == id && | 386 | if(qp->id == id && |
399 | qp->saddr == saddr && | 387 | qp->saddr == saddr && |
400 | qp->daddr == daddr && | 388 | qp->daddr == daddr && |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index e4fe9ee484dd..5d316cb72ec9 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -74,7 +74,7 @@ struct ip6frag_skb_cb | |||
74 | 74 | ||
75 | struct frag_queue | 75 | struct frag_queue |
76 | { | 76 | { |
77 | struct frag_queue *next; | 77 | struct hlist_node list; |
78 | struct list_head lru_list; /* lru list member */ | 78 | struct list_head lru_list; /* lru list member */ |
79 | 79 | ||
80 | __u32 id; /* fragment id */ | 80 | __u32 id; /* fragment id */ |
@@ -95,14 +95,13 @@ struct frag_queue | |||
95 | #define FIRST_IN 2 | 95 | #define FIRST_IN 2 |
96 | #define LAST_IN 1 | 96 | #define LAST_IN 1 |
97 | __u16 nhoffset; | 97 | __u16 nhoffset; |
98 | struct frag_queue **pprev; | ||
99 | }; | 98 | }; |
100 | 99 | ||
101 | /* Hash table. */ | 100 | /* Hash table. */ |
102 | 101 | ||
103 | #define IP6Q_HASHSZ 64 | 102 | #define IP6Q_HASHSZ 64 |
104 | 103 | ||
105 | static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ]; | 104 | static struct hlist_head ip6_frag_hash[IP6Q_HASHSZ]; |
106 | static DEFINE_RWLOCK(ip6_frag_lock); | 105 | static DEFINE_RWLOCK(ip6_frag_lock); |
107 | static u32 ip6_frag_hash_rnd; | 106 | static u32 ip6_frag_hash_rnd; |
108 | static LIST_HEAD(ip6_frag_lru_list); | 107 | static LIST_HEAD(ip6_frag_lru_list); |
@@ -110,9 +109,7 @@ int ip6_frag_nqueues = 0; | |||
110 | 109 | ||
111 | static __inline__ void __fq_unlink(struct frag_queue *fq) | 110 | static __inline__ void __fq_unlink(struct frag_queue *fq) |
112 | { | 111 | { |
113 | if(fq->next) | 112 | hlist_del(&fq->list); |
114 | fq->next->pprev = fq->pprev; | ||
115 | *fq->pprev = fq->next; | ||
116 | list_del(&fq->lru_list); | 113 | list_del(&fq->lru_list); |
117 | ip6_frag_nqueues--; | 114 | ip6_frag_nqueues--; |
118 | } | 115 | } |
@@ -163,28 +160,21 @@ static void ip6_frag_secret_rebuild(unsigned long dummy) | |||
163 | get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32)); | 160 | get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32)); |
164 | for (i = 0; i < IP6Q_HASHSZ; i++) { | 161 | for (i = 0; i < IP6Q_HASHSZ; i++) { |
165 | struct frag_queue *q; | 162 | struct frag_queue *q; |
163 | struct hlist_node *p, *n; | ||
166 | 164 | ||
167 | q = ip6_frag_hash[i]; | 165 | hlist_for_each_entry_safe(q, p, n, &ip6_frag_hash[i], list) { |
168 | while (q) { | ||
169 | struct frag_queue *next = q->next; | ||
170 | unsigned int hval = ip6qhashfn(q->id, | 166 | unsigned int hval = ip6qhashfn(q->id, |
171 | &q->saddr, | 167 | &q->saddr, |
172 | &q->daddr); | 168 | &q->daddr); |
173 | 169 | ||
174 | if (hval != i) { | 170 | if (hval != i) { |
175 | /* Unlink. */ | 171 | hlist_del(&q->list); |
176 | if (q->next) | ||
177 | q->next->pprev = q->pprev; | ||
178 | *q->pprev = q->next; | ||
179 | 172 | ||
180 | /* Relink to new hash chain. */ | 173 | /* Relink to new hash chain. */ |
181 | if ((q->next = ip6_frag_hash[hval]) != NULL) | 174 | hlist_add_head(&q->list, |
182 | q->next->pprev = &q->next; | 175 | &ip6_frag_hash[hval]); |
183 | ip6_frag_hash[hval] = q; | ||
184 | q->pprev = &ip6_frag_hash[hval]; | ||
185 | } | ||
186 | 176 | ||
187 | q = next; | 177 | } |
188 | } | 178 | } |
189 | } | 179 | } |
190 | write_unlock(&ip6_frag_lock); | 180 | write_unlock(&ip6_frag_lock); |
@@ -337,10 +327,13 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash, | |||
337 | struct frag_queue *fq_in) | 327 | struct frag_queue *fq_in) |
338 | { | 328 | { |
339 | struct frag_queue *fq; | 329 | struct frag_queue *fq; |
330 | #ifdef CONFIG_SMP | ||
331 | struct hlist_node *n; | ||
332 | #endif | ||
340 | 333 | ||
341 | write_lock(&ip6_frag_lock); | 334 | write_lock(&ip6_frag_lock); |
342 | #ifdef CONFIG_SMP | 335 | #ifdef CONFIG_SMP |
343 | for (fq = ip6_frag_hash[hash]; fq; fq = fq->next) { | 336 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { |
344 | if (fq->id == fq_in->id && | 337 | if (fq->id == fq_in->id && |
345 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && | 338 | ipv6_addr_equal(&fq_in->saddr, &fq->saddr) && |
346 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { | 339 | ipv6_addr_equal(&fq_in->daddr, &fq->daddr)) { |
@@ -358,10 +351,7 @@ static struct frag_queue *ip6_frag_intern(unsigned int hash, | |||
358 | atomic_inc(&fq->refcnt); | 351 | atomic_inc(&fq->refcnt); |
359 | 352 | ||
360 | atomic_inc(&fq->refcnt); | 353 | atomic_inc(&fq->refcnt); |
361 | if((fq->next = ip6_frag_hash[hash]) != NULL) | 354 | hlist_add_head(&fq->list, &ip6_frag_hash[hash]); |
362 | fq->next->pprev = &fq->next; | ||
363 | ip6_frag_hash[hash] = fq; | ||
364 | fq->pprev = &ip6_frag_hash[hash]; | ||
365 | INIT_LIST_HEAD(&fq->lru_list); | 355 | INIT_LIST_HEAD(&fq->lru_list); |
366 | list_add_tail(&fq->lru_list, &ip6_frag_lru_list); | 356 | list_add_tail(&fq->lru_list, &ip6_frag_lru_list); |
367 | ip6_frag_nqueues++; | 357 | ip6_frag_nqueues++; |
@@ -401,10 +391,11 @@ static __inline__ struct frag_queue * | |||
401 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) | 391 | fq_find(u32 id, struct in6_addr *src, struct in6_addr *dst) |
402 | { | 392 | { |
403 | struct frag_queue *fq; | 393 | struct frag_queue *fq; |
394 | struct hlist_node *n; | ||
404 | unsigned int hash = ip6qhashfn(id, src, dst); | 395 | unsigned int hash = ip6qhashfn(id, src, dst); |
405 | 396 | ||
406 | read_lock(&ip6_frag_lock); | 397 | read_lock(&ip6_frag_lock); |
407 | for(fq = ip6_frag_hash[hash]; fq; fq = fq->next) { | 398 | hlist_for_each_entry(fq, n, &ip6_frag_hash[hash], list) { |
408 | if (fq->id == id && | 399 | if (fq->id == id && |
409 | ipv6_addr_equal(src, &fq->saddr) && | 400 | ipv6_addr_equal(src, &fq->saddr) && |
410 | ipv6_addr_equal(dst, &fq->daddr)) { | 401 | ipv6_addr_equal(dst, &fq->daddr)) { |