inetpeer: inetpeer_invalidate_tree() cleanup
[deliverable/linux.git] / net / ipv4 / inetpeer.c
index cac02ad1425d883f2a196548a88cb24fba85772a..da90a8cab6143b76edda2aee5ccb147e793c49b6 100644 (file)
@@ -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);
This page took 0.028995 seconds and 5 git commands to generate.