[Devel] [PATCH RHEL7 COMMIT] sunrpc: add "kill-tasks" proc entry
Konstantin Khorenko
khorenko at virtuozzo.com
Tue Jun 27 13:05:54 MSK 2017
The commit is pushed to "branch-rh7-3.10.0-514.16.1.vz7.32.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.16.1.vz7.32.11
------>
commit fe227d5b345ea8de62f5455c498bd12f3c95aef5
Author: Stanislav Kinsburskiy <skinsbursky at virtuozzo.com>
Date: Tue Jun 27 14:05:53 2017 +0400
sunrpc: add "kill-tasks" proc entry
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>
---
include/linux/sunrpc/clnt.h | 4 +++
net/sunrpc/clnt.c | 71 +++++++++++++++++++++++++++++++++++++++++++++
net/sunrpc/netns.h | 3 ++
net/sunrpc/stats.c | 8 +++++
4 files changed, 86 insertions(+)
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 131032f..597e5ae 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -182,5 +182,9 @@ const char *rpc_peeraddr2str(struct rpc_clnt *, enum rpc_display_format_t);
int rpc_localaddr(struct rpc_clnt *, struct sockaddr *, size_t);
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);
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SUNRPC_CLNT_H */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 23608eb..e64f751 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2536,3 +2536,74 @@ retry:
}
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 file_operations kill_tasks_ops = {
+ .open = nonseekable_open,
+ .write = write_kill_tasks,
+ .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 df58268..b0150ae 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -32,6 +32,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 int sunrpc_net_id;
diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
index 80d3401..f621756 100644
--- a/net/sunrpc/stats.c
+++ b/net/sunrpc/stats.c
@@ -287,6 +287,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);
@@ -294,12 +295,19 @@ 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);
}
More information about the Devel
mailing list