inetpeer.c (e5451c8f8330e03ad3cfa16048b4daf961af434f) inetpeer.c (1cc9a98b59ba92fece1277f76aa43e05f34936a6)
1/*
2 * INETPEER - A storage for permanent information about peers
3 *
4 * This source is covered by the GNU GPL, the same as all kernel sources.
5 *
6 * Authors: Andrey V. Savochkin <saw@msu.ru>
7 */
8

--- 101 unchanged lines hidden (view full) ---

110 c = rcu_dereference_protected(p->avl_right, 1);
111 if (c != peer_avl_empty) {
112 list_add_tail(&c->gc_list, &list);
113 p->avl_right = peer_avl_empty_rcu;
114 }
115
116 n = list_entry(p->gc_list.next, struct inet_peer, gc_list);
117
1/*
2 * INETPEER - A storage for permanent information about peers
3 *
4 * This source is covered by the GNU GPL, the same as all kernel sources.
5 *
6 * Authors: Andrey V. Savochkin <saw@msu.ru>
7 */
8

--- 101 unchanged lines hidden (view full) ---

110 c = rcu_dereference_protected(p->avl_right, 1);
111 if (c != peer_avl_empty) {
112 list_add_tail(&c->gc_list, &list);
113 p->avl_right = peer_avl_empty_rcu;
114 }
115
116 n = list_entry(p->gc_list.next, struct inet_peer, gc_list);
117
118 if (!atomic_read(&p->refcnt)) {
118 if (refcount_read(&p->refcnt) == 1) {
119 list_del(&p->gc_list);
120 kmem_cache_free(peer_cachep, p);
121 }
122 }
123
124 if (list_empty(&list))
125 return;
126

--- 70 unchanged lines hidden (view full) ---

197{
198 struct inet_peer *u = rcu_dereference(base->root);
199 int count = 0;
200
201 while (u != peer_avl_empty) {
202 int cmp = inetpeer_addr_cmp(daddr, &u->daddr);
203 if (cmp == 0) {
204 /* Before taking a reference, check if this entry was
119 list_del(&p->gc_list);
120 kmem_cache_free(peer_cachep, p);
121 }
122 }
123
124 if (list_empty(&list))
125 return;
126

--- 70 unchanged lines hidden (view full) ---

197{
198 struct inet_peer *u = rcu_dereference(base->root);
199 int count = 0;
200
201 while (u != peer_avl_empty) {
202 int cmp = inetpeer_addr_cmp(daddr, &u->daddr);
203 if (cmp == 0) {
204 /* Before taking a reference, check if this entry was
205 * deleted (refcnt=-1)
205 * deleted (refcnt=0)
206 */
206 */
207 if (!atomic_add_unless(&u->refcnt, 1, -1))
207 if (!refcount_inc_not_zero(&u->refcnt)) {
208 u = NULL;
208 u = NULL;
209 }
209 return u;
210 }
211 if (cmp == -1)
212 u = rcu_dereference(u->avl_left);
213 else
214 u = rcu_dereference(u->avl_right);
215 if (unlikely(++count == PEER_MAXDEPTH))
216 break;

--- 160 unchanged lines hidden (view full) ---

377 else
378 ttl = inet_peer_maxttl
379 - (inet_peer_maxttl - inet_peer_minttl) / HZ *
380 base->total / inet_peer_threshold * HZ;
381 stackptr--; /* last stack slot is peer_avl_empty */
382 while (stackptr > stack) {
383 stackptr--;
384 p = rcu_deref_locked(**stackptr, base);
210 return u;
211 }
212 if (cmp == -1)
213 u = rcu_dereference(u->avl_left);
214 else
215 u = rcu_dereference(u->avl_right);
216 if (unlikely(++count == PEER_MAXDEPTH))
217 break;

--- 160 unchanged lines hidden (view full) ---

378 else
379 ttl = inet_peer_maxttl
380 - (inet_peer_maxttl - inet_peer_minttl) / HZ *
381 base->total / inet_peer_threshold * HZ;
382 stackptr--; /* last stack slot is peer_avl_empty */
383 while (stackptr > stack) {
384 stackptr--;
385 p = rcu_deref_locked(**stackptr, base);
385 if (atomic_read(&p->refcnt) == 0) {
386 if (refcount_read(&p->refcnt) == 1) {
386 smp_rmb();
387 delta = (__u32)jiffies - p->dtime;
387 smp_rmb();
388 delta = (__u32)jiffies - p->dtime;
388 if (delta >= ttl &&
389 atomic_cmpxchg(&p->refcnt, 0, -1) == 0) {
389 if (delta >= ttl && refcount_dec_if_one(&p->refcnt)) {
390 p->gc_next = gchead;
391 gchead = p;
392 }
393 }
394 }
395 while ((p = gchead) != NULL) {
396 gchead = p->gc_next;
397 cnt++;

--- 29 unchanged lines hidden (view full) ---

427
428 /* retry an exact lookup, taking the lock before.
429 * At least, nodes should be hot in our cache.
430 */
431 write_seqlock_bh(&base->lock);
432relookup:
433 p = lookup(daddr, stack, base);
434 if (p != peer_avl_empty) {
390 p->gc_next = gchead;
391 gchead = p;
392 }
393 }
394 }
395 while ((p = gchead) != NULL) {
396 gchead = p->gc_next;
397 cnt++;

--- 29 unchanged lines hidden (view full) ---

427
428 /* retry an exact lookup, taking the lock before.
429 * At least, nodes should be hot in our cache.
430 */
431 write_seqlock_bh(&base->lock);
432relookup:
433 p = lookup(daddr, stack, base);
434 if (p != peer_avl_empty) {
435 atomic_inc(&p->refcnt);
435 refcount_inc(&p->refcnt);
436 write_sequnlock_bh(&base->lock);
437 return p;
438 }
439 if (!gccnt) {
440 gccnt = inet_peer_gc(base, stack, stackptr);
441 if (gccnt && create)
442 goto relookup;
443 }
444 p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
445 if (p) {
446 p->daddr = *daddr;
436 write_sequnlock_bh(&base->lock);
437 return p;
438 }
439 if (!gccnt) {
440 gccnt = inet_peer_gc(base, stack, stackptr);
441 if (gccnt && create)
442 goto relookup;
443 }
444 p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
445 if (p) {
446 p->daddr = *daddr;
447 atomic_set(&p->refcnt, 1);
447 refcount_set(&p->refcnt, 2);
448 atomic_set(&p->rid, 0);
449 p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
450 p->rate_tokens = 0;
451 /* 60*HZ is arbitrary, but chosen enough high so that the first
452 * calculation of tokens is at its maximum.
453 */
454 p->rate_last = jiffies - 60*HZ;
455 INIT_LIST_HEAD(&p->gc_list);

--- 7 unchanged lines hidden (view full) ---

463 return p;
464}
465EXPORT_SYMBOL_GPL(inet_getpeer);
466
467void inet_putpeer(struct inet_peer *p)
468{
469 p->dtime = (__u32)jiffies;
470 smp_mb__before_atomic();
448 atomic_set(&p->rid, 0);
449 p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
450 p->rate_tokens = 0;
451 /* 60*HZ is arbitrary, but chosen enough high so that the first
452 * calculation of tokens is at its maximum.
453 */
454 p->rate_last = jiffies - 60*HZ;
455 INIT_LIST_HEAD(&p->gc_list);

--- 7 unchanged lines hidden (view full) ---

463 return p;
464}
465EXPORT_SYMBOL_GPL(inet_getpeer);
466
467void inet_putpeer(struct inet_peer *p)
468{
469 p->dtime = (__u32)jiffies;
470 smp_mb__before_atomic();
471 atomic_dec(&p->refcnt);
471 refcount_dec(&p->refcnt);
472}
473EXPORT_SYMBOL_GPL(inet_putpeer);
474
475/*
476 * Check transmit rate limitation for given message.
477 * The rate information is held in the inet_peer entries now.
478 * This function is generic and could be used for other purposes
479 * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.

--- 63 unchanged lines hidden ---
472}
473EXPORT_SYMBOL_GPL(inet_putpeer);
474
475/*
476 * Check transmit rate limitation for given message.
477 * The rate information is held in the inet_peer entries now.
478 * This function is generic and could be used for other purposes
479 * too. It uses a Token bucket filter as suggested by Alexey Kuznetsov.

--- 63 unchanged lines hidden ---