From: Stanislav Kinsburskiy <skinsbur...@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 <skinsbur...@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.yushche...@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 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel