Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaa908ff authored by Cong Wang's avatar Cong Wang Committed by David S. Miller
Browse files

net_sched: switch to rcu_work



Commit 05f0fe6b ("RCU, workqueue: Implement rcu_work") introduces
new API's for dispatching work in a RCU callback. Now we can just
switch to the new API's for tc filters. This could get rid of a lot
of code.

Cc: Tejun Heo <tj@kernel.org>
Cc: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: default avatarCong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1bb58d2d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ struct tcf_block_ext_info {
};

struct tcf_block_cb;
bool tcf_queue_work(struct work_struct *work);
bool tcf_queue_work(struct rcu_work *rwork, work_func_t func);

#ifdef CONFIG_NET_CLS
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
+3 −2
Original line number Diff line number Diff line
@@ -103,9 +103,10 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
}
EXPORT_SYMBOL(unregister_tcf_proto_ops);

bool tcf_queue_work(struct work_struct *work)
bool tcf_queue_work(struct rcu_work *rwork, work_func_t func)
{
	return queue_work(tc_filter_wq, work);
	INIT_RCU_WORK(rwork, func);
	return queue_rcu_work(tc_filter_wq, rwork);
}
EXPORT_SYMBOL(tcf_queue_work);

+7 −17
Original line number Diff line number Diff line
@@ -35,10 +35,7 @@ struct basic_filter {
	struct tcf_result	res;
	struct tcf_proto	*tp;
	struct list_head	link;
	union {
		struct work_struct	work;
		struct rcu_head		rcu;
	};
	struct rcu_work		rwork;
};

static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -97,21 +94,14 @@ static void __basic_delete_filter(struct basic_filter *f)

static void basic_delete_filter_work(struct work_struct *work)
{
	struct basic_filter *f = container_of(work, struct basic_filter, work);

	struct basic_filter *f = container_of(to_rcu_work(work),
					      struct basic_filter,
					      rwork);
	rtnl_lock();
	__basic_delete_filter(f);
	rtnl_unlock();
}

static void basic_delete_filter(struct rcu_head *head)
{
	struct basic_filter *f = container_of(head, struct basic_filter, rcu);

	INIT_WORK(&f->work, basic_delete_filter_work);
	tcf_queue_work(&f->work);
}

static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
{
	struct basic_head *head = rtnl_dereference(tp->root);
@@ -122,7 +112,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
		tcf_unbind_filter(tp, &f->res);
		idr_remove(&head->handle_idr, f->handle);
		if (tcf_exts_get_net(&f->exts))
			call_rcu(&f->rcu, basic_delete_filter);
			tcf_queue_work(&f->rwork, basic_delete_filter_work);
		else
			__basic_delete_filter(f);
	}
@@ -140,7 +130,7 @@ static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
	tcf_unbind_filter(tp, &f->res);
	idr_remove(&head->handle_idr, f->handle);
	tcf_exts_get_net(&f->exts);
	call_rcu(&f->rcu, basic_delete_filter);
	tcf_queue_work(&f->rwork, basic_delete_filter_work);
	*last = list_empty(&head->flist);
	return 0;
}
@@ -234,7 +224,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb,
		list_replace_rcu(&fold->link, &fnew->link);
		tcf_unbind_filter(tp, &fold->res);
		tcf_exts_get_net(&fold->exts);
		call_rcu(&fold->rcu, basic_delete_filter);
		tcf_queue_work(&fold->rwork, basic_delete_filter_work);
	} else {
		list_add_rcu(&fnew->link, &head->flist);
	}
+6 −16
Original line number Diff line number Diff line
@@ -49,10 +49,7 @@ struct cls_bpf_prog {
	struct sock_filter *bpf_ops;
	const char *bpf_name;
	struct tcf_proto *tp;
	union {
		struct work_struct work;
		struct rcu_head rcu;
	};
	struct rcu_work rwork;
};

static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = {
@@ -275,21 +272,14 @@ static void __cls_bpf_delete_prog(struct cls_bpf_prog *prog)

static void cls_bpf_delete_prog_work(struct work_struct *work)
{
	struct cls_bpf_prog *prog = container_of(work, struct cls_bpf_prog, work);

	struct cls_bpf_prog *prog = container_of(to_rcu_work(work),
						 struct cls_bpf_prog,
						 rwork);
	rtnl_lock();
	__cls_bpf_delete_prog(prog);
	rtnl_unlock();
}

static void cls_bpf_delete_prog_rcu(struct rcu_head *rcu)
{
	struct cls_bpf_prog *prog = container_of(rcu, struct cls_bpf_prog, rcu);

	INIT_WORK(&prog->work, cls_bpf_delete_prog_work);
	tcf_queue_work(&prog->work);
}

static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
			     struct netlink_ext_ack *extack)
{
@@ -300,7 +290,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog,
	list_del_rcu(&prog->link);
	tcf_unbind_filter(tp, &prog->res);
	if (tcf_exts_get_net(&prog->exts))
		call_rcu(&prog->rcu, cls_bpf_delete_prog_rcu);
		tcf_queue_work(&prog->rwork, cls_bpf_delete_prog_work);
	else
		__cls_bpf_delete_prog(prog);
}
@@ -526,7 +516,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
		list_replace_rcu(&oldprog->link, &prog->link);
		tcf_unbind_filter(tp, &oldprog->res);
		tcf_exts_get_net(&oldprog->exts);
		call_rcu(&oldprog->rcu, cls_bpf_delete_prog_rcu);
		tcf_queue_work(&oldprog->rwork, cls_bpf_delete_prog_work);
	} else {
		list_add_rcu(&prog->link, &head->plist);
	}
+5 −18
Original line number Diff line number Diff line
@@ -23,10 +23,7 @@ struct cls_cgroup_head {
	struct tcf_exts		exts;
	struct tcf_ematch_tree	ematches;
	struct tcf_proto	*tp;
	union {
		struct work_struct	work;
		struct rcu_head		rcu;
	};
	struct rcu_work		rwork;
};

static int cls_cgroup_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -70,24 +67,14 @@ static void __cls_cgroup_destroy(struct cls_cgroup_head *head)

static void cls_cgroup_destroy_work(struct work_struct *work)
{
	struct cls_cgroup_head *head = container_of(work,
	struct cls_cgroup_head *head = container_of(to_rcu_work(work),
						    struct cls_cgroup_head,
						    work);
						    rwork);
	rtnl_lock();
	__cls_cgroup_destroy(head);
	rtnl_unlock();
}

static void cls_cgroup_destroy_rcu(struct rcu_head *root)
{
	struct cls_cgroup_head *head = container_of(root,
						    struct cls_cgroup_head,
						    rcu);

	INIT_WORK(&head->work, cls_cgroup_destroy_work);
	tcf_queue_work(&head->work);
}

static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
			     struct tcf_proto *tp, unsigned long base,
			     u32 handle, struct nlattr **tca,
@@ -134,7 +121,7 @@ static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
	rcu_assign_pointer(tp->root, new);
	if (head) {
		tcf_exts_get_net(&head->exts);
		call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
		tcf_queue_work(&head->rwork, cls_cgroup_destroy_work);
	}
	return 0;
errout:
@@ -151,7 +138,7 @@ static void cls_cgroup_destroy(struct tcf_proto *tp,
	/* Head can still be NULL due to cls_cgroup_init(). */
	if (head) {
		if (tcf_exts_get_net(&head->exts))
			call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
			tcf_queue_work(&head->rwork, cls_cgroup_destroy_work);
		else
			__cls_cgroup_destroy(head);
	}
Loading