net_sched: convert tcf_hashinfo to hlist and use spinlock
[cascardo/linux.git] / net / sched / act_police.c
index f201576..0cc305e 100644 (file)
@@ -60,18 +60,19 @@ struct tc_police_compat {
 static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
                              int type, struct tc_action *a)
 {
+       struct hlist_head *head;
        struct tcf_common *p;
        int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
        struct nlattr *nest;
 
-       read_lock_bh(&police_hash_info.lock);
+       spin_lock_bh(&police_hash_info.lock);
 
        s_i = cb->args[0];
 
        for (i = 0; i < (POL_TAB_MASK + 1); i++) {
-               p = police_hash_info.htab[tcf_hash(i, POL_TAB_MASK)];
+               head = &police_hash_info.htab[tcf_hash(i, POL_TAB_MASK)];
 
-               for (; p; p = p->tcfc_next) {
+               hlist_for_each_entry_rcu(p, head, tcfc_head) {
                        index++;
                        if (index < s_i)
                                continue;
@@ -94,7 +95,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
                }
        }
 done:
-       read_unlock_bh(&police_hash_info.lock);
+       spin_unlock_bh(&police_hash_info.lock);
        if (n_i)
                cb->args[0] += n_i;
        return n_i;
@@ -106,25 +107,16 @@ nla_put_failure:
 
 static void tcf_police_destroy(struct tcf_police *p)
 {
-       unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
-       struct tcf_common **p1p;
-
-       for (p1p = &police_hash_info.htab[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
-               if (*p1p == &p->common) {
-                       write_lock_bh(&police_hash_info.lock);
-                       *p1p = p->tcf_next;
-                       write_unlock_bh(&police_hash_info.lock);
-                       gen_kill_estimator(&p->tcf_bstats,
-                                          &p->tcf_rate_est);
-                       /*
-                        * gen_estimator est_timer() might access p->tcf_lock
-                        * or bstats, wait a RCU grace period before freeing p
-                        */
-                       kfree_rcu(p, tcf_rcu);
-                       return;
-               }
-       }
-       WARN_ON(1);
+       spin_lock_bh(&police_hash_info.lock);
+       hlist_del(&p->tcf_head);
+       spin_unlock_bh(&police_hash_info.lock);
+       gen_kill_estimator(&p->tcf_bstats,
+                          &p->tcf_rate_est);
+       /*
+        * gen_estimator est_timer() might access p->tcf_lock
+        * or bstats, wait a RCU grace period before freeing p
+        */
+       kfree_rcu(p, tcf_rcu);
 }
 
 static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
@@ -259,10 +251,9 @@ override:
        police->tcf_index = parm->index ? parm->index :
                tcf_hash_new_index(&police_idx_gen, &police_hash_info);
        h = tcf_hash(police->tcf_index, POL_TAB_MASK);
-       write_lock_bh(&police_hash_info.lock);
-       police->tcf_next = police_hash_info.htab[h];
-       police_hash_info.htab[h] = &police->common;
-       write_unlock_bh(&police_hash_info.lock);
+       spin_lock_bh(&police_hash_info.lock);
+       hlist_add_head(&police->tcf_head, &police_hash_info.htab[h]);
+       spin_unlock_bh(&police_hash_info.lock);
 
        a->priv = police;
        return ret;