net sched actions: fix GETing actions

With the batch changes that translated transient actions into
a temporary list lost in the translation was the fact that
tcf_action_destroy() will eventually delete the action from
the permanent location if the refcount is zero.

Example of what broke:
...add a gact action to drop
sudo $TC actions add action drop index 10
...now retrieve it, looks good
sudo $TC actions get action gact index 10
...retrieve it again and find it is gone!
sudo $TC actions get action gact index 10

Fixes: 22dc13c837 ("net_sched: convert tcf_exts from list to pointer array"),
Fixes: 824a7e8863 ("net_sched: remove an unnecessary list_del()")
Fixes: f07fed82ad ("net_sched: remove the leftover cleanup_a()")

Acked-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jamal Hadi Salim 2016-09-19 19:02:51 -04:00 коммит произвёл David S. Miller
Родитель 1d9423ae0d
Коммит aecc5cefc3
1 изменённых файлов: 20 добавлений и 0 удалений

Просмотреть файл

@ -592,6 +592,17 @@ err_out:
return ERR_PTR(err); return ERR_PTR(err);
} }
static void cleanup_a(struct list_head *actions, int ovr)
{
struct tc_action *a;
if (!ovr)
return;
list_for_each_entry(a, actions, list)
a->tcfa_refcnt--;
}
int tcf_action_init(struct net *net, struct nlattr *nla, struct nlattr *est, int tcf_action_init(struct net *net, struct nlattr *nla, struct nlattr *est,
char *name, int ovr, int bind, struct list_head *actions) char *name, int ovr, int bind, struct list_head *actions)
{ {
@ -611,8 +622,15 @@ int tcf_action_init(struct net *net, struct nlattr *nla, struct nlattr *est,
goto err; goto err;
} }
act->order = i; act->order = i;
if (ovr)
act->tcfa_refcnt++;
list_add_tail(&act->list, actions); list_add_tail(&act->list, actions);
} }
/* Remove the temp refcnt which was necessary to protect against
* destroying an existing action which was being replaced
*/
cleanup_a(actions, ovr);
return 0; return 0;
err: err:
@ -882,6 +900,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
goto err; goto err;
} }
act->order = i; act->order = i;
if (event == RTM_GETACTION)
act->tcfa_refcnt++;
list_add_tail(&act->list, &actions); list_add_tail(&act->list, &actions);
} }