Linux NFS development
 help / color / mirror / Atom feed
From: Jeff Layton <jlayton@kernel.org>
To: Trond Myklebust <trondmy@kernel.org>,
	Anna Schumaker <anna@kernel.org>,
	 Chuck Lever <chuck.lever@oracle.com>, Neil Brown <neilb@suse.de>,
	 Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <Dai.Ngo@oracle.com>,  Tom Talpey <tom@talpey.com>,
	"David S. Miller" <davem@davemloft.net>,
	 Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>,
	 Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>
Cc: Josef Bacik <josef@toxicpanda.com>,
	 Benjamin Coddington <bcodding@redhat.com>,
	linux-nfs@vger.kernel.org,  linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org,  Jeff Layton <jlayton@kernel.org>
Subject: [PATCH RFC 5/9] nfs: don't hold a reference to struct net in struct nfs_client
Date: Mon, 17 Mar 2025 16:59:57 -0400	[thread overview]
Message-ID: <20250317-rpc-shutdown-v1-5-85ba8e20b75d@kernel.org> (raw)
In-Reply-To: <20250317-rpc-shutdown-v1-0-85ba8e20b75d@kernel.org>

An NFS client holds a reference to the net namespace. This can cause
nfs_clients to stick around after a container dies spontaneously.

The container orchestrator sees that there are no more tasks in the
container, detaches the filesystems and tears down the networking.
Unfortunately, there can still be RPCs in flight that will end up
attempting to retransmit indefinitely. No userland tasks have a way
to reach that net namespace any longer though, so there is no hope of it
being rescued.

Instead of keeping a net reference in struct nfs_client, add a nfs_net
pre_exit routine that kills off the nfs_server and any remaining
nfs_clients, and then waits for the nfs_client_list to go empty.

Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
 fs/nfs/client.c |  6 ++++--
 fs/nfs/inode.c  | 28 ++++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 3b0918ade53cd331d76baaa86fd2adec5d945b78..8f41cb88f88c2b4d7f10424484b6e70ac2b8835a 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -180,7 +180,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 	clp->cl_proto = cl_init->proto;
 	clp->cl_nconnect = cl_init->nconnect;
 	clp->cl_max_connect = cl_init->max_connect ? cl_init->max_connect : 1;
-	clp->cl_net = get_net(cl_init->net);
+	clp->cl_net = cl_init->net;
 
 #if IS_ENABLED(CONFIG_NFS_LOCALIO)
 	seqlock_init(&clp->cl_boot_lock);
@@ -244,13 +244,15 @@ static void pnfs_init_server(struct nfs_server *server)
  */
 void nfs_free_client(struct nfs_client *clp)
 {
+	struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
+
 	nfs_localio_disable_client(clp);
 
 	/* -EIO all pending I/O */
 	if (!IS_ERR(clp->cl_rpcclient))
 		rpc_shutdown_client(clp->cl_rpcclient);
 
-	put_net(clp->cl_net);
+	wake_up_var(&nn->nfs_client_list);
 	put_nfs_version(clp->cl_nfs_mod);
 	kfree(clp->cl_hostname);
 	kfree(clp->cl_acceptor);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 1aa67fca69b2fbd8afb1c51be78198220b1e13c7..0352e7e6ee270562a971d031ba02bdec96496288 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2562,9 +2562,37 @@ static void nfs_net_exit(struct net *net)
 	nfs_clients_exit(net);
 }
 
+static bool all_clients_gone(struct nfs_net *nn)
+{
+	bool	gone;
+
+	spin_lock(&nn->nfs_client_lock);
+	gone = list_empty(&nn->nfs_client_list);
+	spin_unlock(&nn->nfs_client_lock);
+
+	return gone;
+}
+
+static void nfs_net_pre_exit(struct net *net)
+{
+	struct nfs_net *nn = net_generic(net, nfs_net_id);
+	struct nfs_server *server;
+	struct nfs_client *clp;
+
+	spin_lock(&nn->nfs_client_lock);
+	list_for_each_entry(server, &nn->nfs_volume_list, master_link)
+		nfs_server_shutdown(server);
+	list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link)
+		rpc_clnt_shutdown(clp->cl_rpcclient);
+	spin_unlock(&nn->nfs_client_lock);
+
+	wait_var_event(&nn->nfs_client_list, all_clients_gone(nn));
+}
+
 static struct pernet_operations nfs_net_ops = {
 	.init = nfs_net_init,
 	.exit = nfs_net_exit,
+	.pre_exit = nfs_net_pre_exit,
 	.id   = &nfs_net_id,
 	.size = sizeof(struct nfs_net),
 };

-- 
2.48.1


  parent reply	other threads:[~2025-03-17 21:00 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-17 20:59 [PATCH RFC 0/9] nfs/sunrpc: stop holding netns references in client-side NFS and RPC objects Jeff Layton
2025-03-17 20:59 ` [PATCH RFC 1/9] sunrpc: transplant shutdown_client() to sunrpc module Jeff Layton
2025-03-17 20:59 ` [PATCH RFC 2/9] lockd: add a helper to shut down rpc_clnt in nlm_host Jeff Layton
2025-03-17 20:59 ` [PATCH RFC 3/9] lockd: don't #include debug.h from lockd.h Jeff Layton
2025-03-17 20:59 ` [PATCH RFC 4/9] nfs: transplant nfs_server shutdown into a helper function Jeff Layton
2025-03-17 20:59 ` Jeff Layton [this message]
2025-03-17 20:59 ` [PATCH RFC 6/9] auth_gss: shut down gssproxy rpc_clnt in net pre_exit Jeff Layton
2025-03-17 20:59 ` [PATCH RFC 7/9] auth_gss: don't hold a net reference in gss_auth Jeff Layton
2025-03-17 21:00 ` [PATCH RFC 8/9] sunrpc: don't hold a struct net reference in rpc_xprt Jeff Layton
2025-03-17 21:00 ` [PATCH RFC 9/9] sunrpc: don't upgrade passive net reference in xs_create_sock Jeff Layton
2025-03-17 21:28   ` Trond Myklebust
2025-03-17 21:36     ` Jeff Layton
2025-03-17 21:37       ` Trond Myklebust
2025-03-17 21:41         ` Jeff Layton
2025-03-17 21:35 ` [PATCH RFC 0/9] nfs/sunrpc: stop holding netns references in client-side NFS and RPC objects Trond Myklebust
2025-03-17 21:57   ` Jeff Layton
2025-03-17 22:11     ` Trond Myklebust
2025-03-18 11:30       ` Jeff Layton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250317-rpc-shutdown-v1-5-85ba8e20b75d@kernel.org \
    --to=jlayton@kernel.org \
    --cc=Dai.Ngo@oracle.com \
    --cc=anna@kernel.org \
    --cc=bcodding@redhat.com \
    --cc=chuck.lever@oracle.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=josef@toxicpanda.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neilb@suse.de \
    --cc=netdev@vger.kernel.org \
    --cc=okorniev@redhat.com \
    --cc=pabeni@redhat.com \
    --cc=tom@talpey.com \
    --cc=trondmy@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox