[PATCH 7/9] NFS: add sysfs shutdown knob
From: Benjamin Coddington <hidden>
Date: 2023-04-21 17:20:10
Subsystem:
filesystems (vfs and infrastructure), kernel nfsd, sunrpc, and lockd servers, networking [general], nfs, sunrpc, and lockd clients, the rest · Maintainers:
Alexander Viro, Christian Brauner, Chuck Lever, Jeff Layton, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Trond Myklebust, Anna Schumaker, Linus Torvalds
Within each nfs_server sysfs tree, add an entry named "shutdown". Writing 1 to this file will set the cl_shutdown bit on the rpc_clnt structs associated with that mount. If cl_shutdown is set, the task scheduler immediately returns -EIO for new tasks. Signed-off-by: Benjamin Coddington <redacted> --- fs/nfs/sysfs.c | 46 +++++++++++++++++++++++++++++++++++++ include/linux/nfs_fs_sb.h | 1 + include/linux/sunrpc/clnt.h | 3 ++- net/sunrpc/clnt.c | 5 ++++ 4 files changed, 54 insertions(+), 1 deletion(-)
diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c
index e1b5df7a3df5..09fde2719495 100644
--- a/fs/nfs/sysfs.c
+++ b/fs/nfs/sysfs.c@@ -12,6 +12,7 @@ #include <linux/string.h> #include <linux/nfs_fs.h> #include <linux/rcupdate.h> +#include <linux/lockd/lockd.h> #include "nfs4_fs.h" #include "netns.h"
@@ -191,6 +192,50 @@ void nfs_netns_sysfs_destroy(struct nfs_net *netns) } } +static ssize_t +shutdown_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + struct nfs_server *server = container_of(kobj, struct nfs_server, kobj); + bool shutdown = server->flags & NFS_MOUNT_SHUTDOWN; + return sysfs_emit(buf, "%d\n", shutdown); +} + +static ssize_t +shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + struct nfs_server *server; + int ret, val; + + server = container_of(kobj, struct nfs_server, kobj); + + ret = kstrtoint(buf, 0, &val); + if (ret) + return ret; + + if (val != 1) + return -EINVAL; + + /* already shut down? */ + if (server->flags & NFS_MOUNT_SHUTDOWN) + goto out; + + server->flags |= NFS_MOUNT_SHUTDOWN; + server->client->cl_shutdown = 1; + server->nfs_client->cl_rpcclient->cl_shutdown = 1; + + if (!IS_ERR(server->client_acl)) + server->client_acl->cl_shutdown = 1; + + if (server->nlm_host) + server->nlm_host->h_rpcclnt->cl_shutdown = 1; +out: + return count; +} + +static struct kobj_attribute nfs_sysfs_attr_shutdown = __ATTR_RW(shutdown); + #define RPC_CLIENT_NAME_SIZE 64 void nfs_sysfs_link_rpc_client(struct nfs_server *server,
@@ -217,6 +262,7 @@ static void nfs_sysfs_sb_release(struct kobject *kobj) } static struct attribute *nfs_mp_attrs[] = { + &nfs_sysfs_attr_shutdown.attr, NULL, };
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index dee1664abca8..bc89496384ff 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h@@ -153,6 +153,7 @@ struct nfs_server { #define NFS_MOUNT_WRITE_EAGER 0x01000000 #define NFS_MOUNT_WRITE_WAIT 0x02000000 #define NFS_MOUNT_TRUNK_DISCOVERY 0x04000000 +#define NFS_MOUNT_SHUTDOWN 0x08000000 unsigned int fattr_valid; /* Valid attributes */ unsigned int caps; /* server capabilities */
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 4ec718aa91f5..9f72c75a2056 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h@@ -63,7 +63,8 @@ struct rpc_clnt { cl_discrtry : 1,/* disconnect before retry */ cl_noretranstimeo: 1,/* No retransmit timeouts */ cl_autobind : 1,/* use getport() */ - cl_chatty : 1;/* be verbose */ + cl_chatty : 1,/* be verbose */ + cl_shutdown : 1;/* rpc immediate -EIO */ struct rpc_rtt * cl_rtt; /* RTO estimator data */ const struct rpc_timeout *cl_timeout; /* Timeout strategy */
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 0b0b9f1eed46..3c5dca88a918 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c@@ -1717,6 +1717,11 @@ call_start(struct rpc_task *task) trace_rpc_request(task); + if (task->tk_client->cl_shutdown) { + rpc_call_rpcerror(task, -EIO); + return; + } + /* Increment call count (version might not be valid for ping) */ if (clnt->cl_program->version[clnt->cl_vers]) clnt->cl_program->version[clnt->cl_vers]->counts[idx]++;
--
2.39.2