]> Pileus Git - ~andy/linux/blobdiff - net/sched/act_police.c
Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
[~andy/linux] / net / sched / act_police.c
index ef246d87e68bbdf628bc00eebb05e9cb88a3cb87..1778209a332fa1ac251c02beaa97a49cfec747f3 100644 (file)
@@ -41,15 +41,7 @@ struct tcf_police {
        container_of(pc, struct tcf_police, common)
 
 #define POL_TAB_MASK     15
-static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
-static u32 police_idx_gen;
-static DEFINE_RWLOCK(police_lock);
-
-static struct tcf_hashinfo police_hash_info = {
-       .htab   =       tcf_police_ht,
-       .hmask  =       POL_TAB_MASK,
-       .lock   =       &police_lock,
-};
+static struct tcf_hashinfo police_hash_info;
 
 /* old policer structure from before tc actions */
 struct tc_police_compat {
@@ -67,18 +59,20 @@ 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 tcf_hashinfo *hinfo = a->ops->hinfo;
+       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_lock);
+       spin_lock_bh(&hinfo->lock);
 
        s_i = cb->args[0];
 
        for (i = 0; i < (POL_TAB_MASK + 1); i++) {
-               p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)];
+               head = &hinfo->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;
@@ -101,7 +95,7 @@ static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *c
                }
        }
 done:
-       read_unlock_bh(&police_lock);
+       spin_unlock_bh(&hinfo->lock);
        if (n_i)
                cb->args[0] += n_i;
        return n_i;
@@ -111,29 +105,6 @@ nla_put_failure:
        goto done;
 }
 
-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 = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
-               if (*p1p == &p->common) {
-                       write_lock_bh(&police_lock);
-                       *p1p = p->tcf_next;
-                       write_unlock_bh(&police_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);
-}
-
 static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
        [TCA_POLICE_RATE]       = { .len = TC_RTAB_SIZE },
        [TCA_POLICE_PEAKRATE]   = { .len = TC_RTAB_SIZE },
@@ -151,6 +122,7 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
        struct tc_police *parm;
        struct tcf_police *police;
        struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
+       struct tcf_hashinfo *hinfo = a->ops->hinfo;
        int size;
 
        if (nla == NULL)
@@ -168,12 +140,8 @@ static int tcf_act_police_locate(struct net *net, struct nlattr *nla,
        parm = nla_data(tb[TCA_POLICE_TBF]);
 
        if (parm->index) {
-               struct tcf_common *pc;
-
-               pc = tcf_hash_lookup(parm->index, &police_hash_info);
-               if (pc != NULL) {
-                       a->priv = pc;
-                       police = to_police(pc);
+               if (tcf_hash_search(a, parm->index)) {
+                       police = to_police(a->priv);
                        if (bind) {
                                police->tcf_bindcnt += 1;
                                police->tcf_refcnt += 1;
@@ -266,12 +234,11 @@ override:
 
        police->tcfp_t_c = ktime_to_ns(ktime_get());
        police->tcf_index = parm->index ? parm->index :
-               tcf_hash_new_index(&police_idx_gen, &police_hash_info);
+               tcf_hash_new_index(a->ops->hinfo);
        h = tcf_hash(police->tcf_index, POL_TAB_MASK);
-       write_lock_bh(&police_lock);
-       police->tcf_next = tcf_police_ht[h];
-       tcf_police_ht[h] = &police->common;
-       write_unlock_bh(&police_lock);
+       spin_lock_bh(&hinfo->lock);
+       hlist_add_head(&police->tcf_head, &hinfo->htab[h]);
+       spin_unlock_bh(&hinfo->lock);
 
        a->priv = police;
        return ret;
@@ -279,10 +246,8 @@ override:
 failure_unlock:
        spin_unlock_bh(&police->tcf_lock);
 failure:
-       if (P_tab)
-               qdisc_put_rtab(P_tab);
-       if (R_tab)
-               qdisc_put_rtab(R_tab);
+       qdisc_put_rtab(P_tab);
+       qdisc_put_rtab(R_tab);
        if (ret == ACT_P_CREATED)
                kfree(police);
        return err;
@@ -291,19 +256,9 @@ failure:
 static int tcf_act_police_cleanup(struct tc_action *a, int bind)
 {
        struct tcf_police *p = a->priv;
-       int ret = 0;
-
-       if (p != NULL) {
-               if (bind)
-                       p->tcf_bindcnt--;
-
-               p->tcf_refcnt--;
-               if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
-                       tcf_police_destroy(p);
-                       ret = 1;
-               }
-       }
-       return ret;
+       if (p)
+               return tcf_hash_release(&p->common, bind, &police_hash_info);
+       return 0;
 }
 
 static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
@@ -404,7 +359,6 @@ static struct tc_action_ops act_police_ops = {
        .kind           =       "police",
        .hinfo          =       &police_hash_info,
        .type           =       TCA_ID_POLICE,
-       .capab          =       TCA_CAP_NONE,
        .owner          =       THIS_MODULE,
        .act            =       tcf_act_police,
        .dump           =       tcf_act_police_dump,
@@ -416,12 +370,19 @@ static struct tc_action_ops act_police_ops = {
 static int __init
 police_init_module(void)
 {
-       return tcf_register_action(&act_police_ops);
+       int err = tcf_hashinfo_init(&police_hash_info, POL_TAB_MASK);
+       if (err)
+               return err;
+       err = tcf_register_action(&act_police_ops);
+       if (err)
+               tcf_hashinfo_destroy(&police_hash_info);
+       return err;
 }
 
 static void __exit
 police_cleanup_module(void)
 {
+       tcf_hashinfo_destroy(&police_hash_info);
        tcf_unregister_action(&act_police_ops);
 }