Cong Wang <xiyou.wangc...@gmail.com> writes:
[...] > static void cls_cgroup_destroy_work(struct work_struct *work) > { > struct cls_cgroup_head *head = container_of(work, > struct cls_cgroup_head, > work); > rtnl_lock(); > - tcf_exts_destroy(&head->exts); > - tcf_em_tree_destroy(&head->ematches); > - kfree(head); > + __cls_cgroup_destroy(head); > rtnl_unlock(); > } > > @@ -124,8 +130,10 @@ static int cls_cgroup_change(struct net *net, struct > sk_buff *in_skb, > goto errout; > > rcu_assign_pointer(tp->root, new); > - if (head) > + if (head) { > + tcf_exts_get_net(&head->exts); > call_rcu(&head->rcu, cls_cgroup_destroy_rcu); In this case why do you not need to care about success/failure of tcf_exts_get_net() ? > + } > return 0; > errout: > tcf_exts_destroy(&new->exts); > @@ -138,8 +146,12 @@ static void cls_cgroup_destroy(struct tcf_proto *tp) > struct cls_cgroup_head *head = rtnl_dereference(tp->root); > > /* Head can still be NULL due to cls_cgroup_init(). */ > - if (head) > - call_rcu(&head->rcu, cls_cgroup_destroy_rcu); > + if (head) { > + if (tcf_exts_get_net(&head->exts)) > + call_rcu(&head->rcu, cls_cgroup_destroy_rcu); > + else > + __cls_cgroup_destroy(head); > + } > } > > static int cls_cgroup_delete(struct tcf_proto *tp, void *arg, bool *last)