[Devel] [PATCH vz9 10/14] sunrpc: add "kill-tasks" proc entry

Nikita Yushchenko nikita.yushchenko at virtuozzo.com
Mon Sep 27 09:29:56 MSK 2021


From: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>

Boolean per-net SUNPRC proc entry. Will be used to abort SUNRPC traffic when
necessary.

https://jira.sw.ru/browse/PSBM-66510

Signed-off-by: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>

(cherry-picked from vz8 commit 22ca0165a75b ("sunrpc: add "kill-tasks"
proc entry"))

Follow file_operations -> proc_ops migration.

Signed-off-by: Nikita Yushchenko <nikita.yushchenko at virtuozzo.com>
---
 include/linux/sunrpc/clnt.h |  3 ++
 net/sunrpc/clnt.c           | 71 +++++++++++++++++++++++++++++++++++++
 net/sunrpc/netns.h          |  3 ++
 net/sunrpc/stats.c          |  8 +++++
 4 files changed, 85 insertions(+)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 8b5d5c97553e..ac3899388a0d 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -232,6 +232,9 @@ int		rpc_clnt_setup_test_and_add_xprt(struct rpc_clnt *,
 
 const char *rpc_proc_name(const struct rpc_task *task);
 
+int rpc_task_kill_proc_init(struct net *net);
+void rpc_task_kill_proc_fini(struct net *net);
+
 void rpc_clnt_xprt_switch_put(struct rpc_clnt *);
 void rpc_clnt_xprt_switch_add_xprt(struct rpc_clnt *, struct rpc_xprt *);
 bool rpc_clnt_xprt_switch_has_addr(struct rpc_clnt *clnt,
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 8b4de70e8ead..c9b92a1a3eb1 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -3071,3 +3071,74 @@ rpc_clnt_swap_deactivate(struct rpc_clnt *clnt)
 }
 EXPORT_SYMBOL_GPL(rpc_clnt_swap_deactivate);
 #endif /* CONFIG_SUNRPC_SWAP */
+
+static ssize_t write_kill_tasks(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+	char tbuf[20];
+	unsigned long kill_tasks;
+	int res;
+
+	if (*ppos || count > sizeof(tbuf)-1)
+		return -EINVAL;
+	if (copy_from_user(tbuf, buf, count))
+		return -EFAULT;
+
+	tbuf[count] = 0;
+	res = kstrtoul(tbuf, 0, &kill_tasks);
+	if (res)
+		return res;
+
+	sn->kill_tasks = !!kill_tasks;
+	return count;
+}
+
+static ssize_t read_kill_tasks(struct file *file, char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	struct net *net = PDE_DATA(file->f_path.dentry->d_inode);
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+	unsigned long p = *ppos;
+	char tbuf[10];
+	size_t len;
+
+	snprintf(tbuf, sizeof(tbuf), "%d\n", sn->kill_tasks);
+	len = strlen(tbuf);
+	if (p >= len)
+		return 0;
+	len -= p;
+	if (len > count)
+		len = count;
+	if (copy_to_user(buf, (void *)(tbuf+p), len))
+		return -EFAULT;
+	*ppos += len;
+	return len;
+}
+
+static const struct proc_ops kill_tasks_ops = {
+	.proc_open = nonseekable_open,
+	.proc_write = write_kill_tasks,
+	.proc_read = read_kill_tasks,
+};
+
+int rpc_task_kill_proc_init(struct net *net)
+{
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+	sn->kill_tasks = 0;
+	sn->kill_tasks_proc = proc_create_data("kill-tasks",
+					      S_IFREG|S_IRUSR|S_IWUSR,
+					      sn->proc_net_rpc,
+					      &kill_tasks_ops, net);
+	return sn->kill_tasks_proc ? 0 : -ENOMEM;
+}
+
+void rpc_task_kill_proc_fini(struct net *net)
+{
+	struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+	if (sn->kill_tasks_proc)
+		remove_proc_entry("kill-tasks", sn->proc_net_rpc);
+}
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 7ec10b92bea1..14689d6298b9 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -33,6 +33,9 @@ struct sunrpc_net {
 	int pipe_version;
 	atomic_t pipe_users;
 	struct proc_dir_entry *use_gssp_proc;
+
+	bool kill_tasks;
+	struct proc_dir_entry *kill_tasks_proc;
 };
 
 extern unsigned int sunrpc_net_id;
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 77434b2017ad..45541aa49c98 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -326,6 +326,7 @@ EXPORT_SYMBOL_GPL(svc_proc_unregister);
 int rpc_proc_init(struct net *net)
 {
 	struct sunrpc_net *sn;
+	int err;
 
 	dprintk("RPC:       registering /proc/net/rpc\n");
 	sn = net_generic(net, sunrpc_net_id);
@@ -333,11 +334,18 @@ int rpc_proc_init(struct net *net)
 	if (sn->proc_net_rpc == NULL)
 		return -ENOMEM;
 
+	err = rpc_task_kill_proc_init(net);
+	if (err) {
+		remove_proc_entry("rpc", net->proc_net);
+		return err;
+	}
+
 	return 0;
 }
 
 void rpc_proc_exit(struct net *net)
 {
 	dprintk("RPC:       unregistering /proc/net/rpc\n");
+	rpc_task_kill_proc_fini(net);
 	remove_proc_entry("rpc", net->proc_net);
 }
-- 
2.30.2



More information about the Devel mailing list