|
@@ -126,7 +126,7 @@ int inet_peer_maxttl __read_mostly = 10 * 60 * HZ; /* usual time to live: 10 min
|
|
|
|
|
|
static void inetpeer_gc_worker(struct work_struct *work)
|
|
|
{
|
|
|
- struct inet_peer *p, *n;
|
|
|
+ struct inet_peer *p, *n, *c;
|
|
|
LIST_HEAD(list);
|
|
|
|
|
|
spin_lock_bh(&gc_lock);
|
|
@@ -138,17 +138,19 @@ static void inetpeer_gc_worker(struct work_struct *work)
|
|
|
|
|
|
list_for_each_entry_safe(p, n, &list, gc_list) {
|
|
|
|
|
|
- if(need_resched())
|
|
|
+ if (need_resched())
|
|
|
cond_resched();
|
|
|
|
|
|
- if (p->avl_left != peer_avl_empty) {
|
|
|
- list_add_tail(&p->avl_left->gc_list, &list);
|
|
|
- p->avl_left = peer_avl_empty;
|
|
|
+ c = rcu_dereference_protected(p->avl_left, 1);
|
|
|
+ if (c != peer_avl_empty) {
|
|
|
+ list_add_tail(&c->gc_list, &list);
|
|
|
+ p->avl_left = peer_avl_empty_rcu;
|
|
|
}
|
|
|
|
|
|
- if (p->avl_right != peer_avl_empty) {
|
|
|
- list_add_tail(&p->avl_right->gc_list, &list);
|
|
|
- p->avl_right = peer_avl_empty;
|
|
|
+ c = rcu_dereference_protected(p->avl_right, 1);
|
|
|
+ if (c != peer_avl_empty) {
|
|
|
+ list_add_tail(&c->gc_list, &list);
|
|
|
+ p->avl_right = peer_avl_empty_rcu;
|
|
|
}
|
|
|
|
|
|
n = list_entry(p->gc_list.next, struct inet_peer, gc_list);
|
|
@@ -587,23 +589,17 @@ static void inetpeer_inval_rcu(struct rcu_head *head)
|
|
|
|
|
|
void inetpeer_invalidate_tree(struct inet_peer_base *base)
|
|
|
{
|
|
|
- struct inet_peer *old, *new, *prev;
|
|
|
+ struct inet_peer *root;
|
|
|
|
|
|
write_seqlock_bh(&base->lock);
|
|
|
|
|
|
- old = base->root;
|
|
|
- if (old == peer_avl_empty_rcu)
|
|
|
- goto out;
|
|
|
-
|
|
|
- new = peer_avl_empty_rcu;
|
|
|
-
|
|
|
- prev = cmpxchg(&base->root, old, new);
|
|
|
- if (prev == old) {
|
|
|
+ root = rcu_deref_locked(base->root, base);
|
|
|
+ if (root != peer_avl_empty) {
|
|
|
+ base->root = peer_avl_empty_rcu;
|
|
|
base->total = 0;
|
|
|
- call_rcu(&prev->gc_rcu, inetpeer_inval_rcu);
|
|
|
+ call_rcu(&root->gc_rcu, inetpeer_inval_rcu);
|
|
|
}
|
|
|
|
|
|
-out:
|
|
|
write_sequnlock_bh(&base->lock);
|
|
|
}
|
|
|
EXPORT_SYMBOL(inetpeer_invalidate_tree);
|