[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