Commit d9615d16 authored by Benjamin Coddington's avatar Benjamin Coddington Committed by Trond Myklebust
Browse files

NFS: add sysfs shutdown knob



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: default avatarBenjamin Coddington <bcodding@redhat.com>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent f4057ffd
Loading
Loading
Loading
Loading
+53 −1
Original line number Diff line number Diff line
@@ -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"
@@ -216,6 +217,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,
@@ -259,9 +304,16 @@ void nfs_sysfs_add_server(struct nfs_server *server)

	ret = kobject_init_and_add(&server->kobj, &nfs_sb_ktype,
				&nfs_kset->kobj, "server-%d", server->s_sysfs_id);
	if (ret < 0)
	if (ret < 0) {
		pr_warn("NFS: nfs sysfs add server-%d failed (%d)\n",
					server->s_sysfs_id, ret);
		return;
	}
	ret = sysfs_create_file_ns(&server->kobj, &nfs_sysfs_attr_shutdown.attr,
				nfs_netns_server_namespace(&server->kobj));
	if (ret < 0)
		pr_warn("NFS: sysfs_create_file_ns for server-%d failed (%d)\n",
			server->s_sysfs_id, ret);
}
EXPORT_SYMBOL_GPL(nfs_sysfs_add_server);

+1 −0
Original line number Diff line number Diff line
@@ -154,6 +154,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 */
+2 −1
Original line number Diff line number Diff line
@@ -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 xprtsec_parms	cl_xprtsec;	/* transport security policy */

	struct rpc_rtt *	cl_rtt;		/* RTO estimator data */
+5 −0
Original line number Diff line number Diff line
@@ -1724,6 +1724,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]++;