From 70e61b3b5f88d60c70765f9146b3b197fa7dc80c Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Tue, 29 Apr 2025 19:54:49 +0800 Subject: [PATCH] NFS: Shut down the nfs_client only after all the superblocks mainline inclusion from mainline-v6.15-rc1 commit 2d3e998a0bc7fe26a724f87a8ce217848040520e category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC40FO CVE: NA Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2d3e998a0bc7fe26a724f87a8ce217848040520e -------------------------------- The nfs_client manages state for all the superblocks in the "cl_superblocks" list, so it must not be shut down until all of them are gone. Fixes: 7d3e26a054c8 ("NFS: Cancel all existing RPC tasks when shutdown") Reviewed-by: Benjamin Coddington Signed-off-by: Trond Myklebust Signed-off-by: Wang Zhaolong --- fs/nfs/sysfs.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/fs/nfs/sysfs.c b/fs/nfs/sysfs.c index 7b59a40d40c0..784f7c1d003b 100644 --- a/fs/nfs/sysfs.c +++ b/fs/nfs/sysfs.c @@ -14,6 +14,7 @@ #include #include +#include "internal.h" #include "nfs4_fs.h" #include "netns.h" #include "sysfs.h" @@ -228,6 +229,25 @@ static void shutdown_client(struct rpc_clnt *clnt) rpc_cancel_tasks(clnt, -EIO, shutdown_match_client, NULL); } +/* + * Shut down the nfs_client only once all the superblocks + * have been shut down. + */ +static void shutdown_nfs_client(struct nfs_client *clp) +{ + struct nfs_server *server; + rcu_read_lock(); + list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) { + if (!(server->flags & NFS_MOUNT_SHUTDOWN)) { + rcu_read_unlock(); + return; + } + } + rcu_read_unlock(); + nfs_mark_client_ready(clp, -EIO); + shutdown_client(clp->cl_rpcclient); +} + static ssize_t shutdown_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -259,7 +279,6 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, server->flags |= NFS_MOUNT_SHUTDOWN; shutdown_client(server->client); - shutdown_client(server->nfs_client->cl_rpcclient); if (!IS_ERR(server->client_acl)) shutdown_client(server->client_acl); @@ -267,6 +286,7 @@ shutdown_store(struct kobject *kobj, struct kobj_attribute *attr, if (server->nlm_host) shutdown_client(server->nlm_host->h_rpcclnt); out: + shutdown_nfs_client(server->nfs_client); return count; } -- Gitee