[NETFILTER]: nf_conntrack: use RCU for conntrack hash
[firefly-linux-kernel-4.4.55.git] / net / netfilter / nf_conntrack_standalone.c
index d54ca78502c461ee30b014a75f21d8bdf1920cb2..98f0cd31150dc2716737da2ef898e67563f4d507 100644 (file)
@@ -58,12 +58,14 @@ struct ct_iter_state {
 static struct hlist_node *ct_get_first(struct seq_file *seq)
 {
        struct ct_iter_state *st = seq->private;
+       struct hlist_node *n;
 
        for (st->bucket = 0;
             st->bucket < nf_conntrack_htable_size;
             st->bucket++) {
-               if (!hlist_empty(&nf_conntrack_hash[st->bucket]))
-                       return nf_conntrack_hash[st->bucket].first;
+               n = rcu_dereference(nf_conntrack_hash[st->bucket].first);
+               if (n)
+                       return n;
        }
        return NULL;
 }
@@ -73,11 +75,11 @@ static struct hlist_node *ct_get_next(struct seq_file *seq,
 {
        struct ct_iter_state *st = seq->private;
 
-       head = head->next;
+       head = rcu_dereference(head->next);
        while (head == NULL) {
                if (++st->bucket >= nf_conntrack_htable_size)
                        return NULL;
-               head = nf_conntrack_hash[st->bucket].first;
+               head = rcu_dereference(nf_conntrack_hash[st->bucket].first);
        }
        return head;
 }
@@ -93,8 +95,9 @@ static struct hlist_node *ct_get_idx(struct seq_file *seq, loff_t pos)
 }
 
 static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+       __acquires(RCU)
 {
-       read_lock_bh(&nf_conntrack_lock);
+       rcu_read_lock();
        return ct_get_idx(seq, *pos);
 }
 
@@ -105,8 +108,9 @@ static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
 }
 
 static void ct_seq_stop(struct seq_file *s, void *v)
+       __releases(RCU)
 {
-       read_unlock_bh(&nf_conntrack_lock);
+       rcu_read_unlock();
 }
 
 /* return 0 on success, 1 in case of error */
@@ -142,7 +146,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
                       ? (long)(conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
                return -ENOSPC;
 
-       if (l4proto->print_conntrack(s, conntrack))
+       if (l4proto->print_conntrack && l4proto->print_conntrack(s, conntrack))
                return -ENOSPC;
 
        if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,