From: Anna Schumaker <anna.schumaker@oracle.com>
To: Jeff Layton <jlayton@kernel.org>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>
Cc: Omar Sandoval <osandov@osandov.com>,
Sargun Dillon <sargun@sargun.me>,
linux-nfs@vger.kernel.org, linux-kernel@vger.keornel.org
Subject: Re: [PATCH 2/2] nfs: move the nfs4_data_server_cache into struct nfs_net
Date: Thu, 10 Apr 2025 15:39:38 -0400 [thread overview]
Message-ID: <64123840-4fd7-4d76-ae99-c92138d20a4a@oracle.com> (raw)
In-Reply-To: <20250410-nfs-ds-netns-v1-2-cc6236e84190@kernel.org>
Hi Jeff,
On 4/10/25 2:12 PM, Jeff Layton wrote:
> Since struct nfs4_pnfs_ds should not be shared between net namespaces,
> move from a global list of objects to a per-netns list and spinlock.
>
> Tested-by: Sargun Dillon <sargun@sargun.me>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> fs/nfs/client.c | 4 ++++
> fs/nfs/inode.c | 3 +++
> fs/nfs/netns.h | 6 +++++-
> fs/nfs/pnfs_nfs.c | 31 +++++++++++++++++--------------
> 4 files changed, 29 insertions(+), 15 deletions(-)
>
> diff --git a/fs/nfs/client.c b/fs/nfs/client.c
> index 9500b46005b0148a5a9a7d464095ca944de06bb5..81c0f780ff82c8a020fafdb3df72552c8e6e535f 100644
> --- a/fs/nfs/client.c
> +++ b/fs/nfs/client.c
> @@ -1199,6 +1199,10 @@ void nfs_clients_init(struct net *net)
> INIT_LIST_HEAD(&nn->nfs_volume_list);
> #if IS_ENABLED(CONFIG_NFS_V4)
> idr_init(&nn->cb_ident_idr);
> +#if IS_ENABLED(CONFIG_NFS_V4_1)
> + INIT_LIST_HEAD(&nn->nfs4_data_server_cache);
> + spin_lock_init(&nn->nfs4_data_server_lock);
> +#endif
> #endif
> spin_lock_init(&nn->nfs_client_lock);
> nn->boot_time = ktime_get_real();
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index 119e447758b994b34e55e7b28fd4f34fa089e2e1..ee796a726a1e4b0dfbd199cc62176c6802692671 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -2559,6 +2559,9 @@ static int nfs_net_init(struct net *net)
>
> static void nfs_net_exit(struct net *net)
> {
> + struct nfs_net *nn = net_generic(net, nfs_net_id);
> +
> + WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache));
nfs4_data_server_cache is defined under an #if IS_ENABLED(CONFIG_NFS_V4_1) block,
so the compiler complains if this isn't enabled:
fs/nfs/inode.c:2564:32: error: no member named 'nfs4_data_server_cache' in 'struct nfs_net'
2564 | WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache));
Anna
> rpc_proc_unregister(net, "nfs");
> nfs_fs_proc_net_exit(net);
> nfs_clients_exit(net);
> diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h
> index a68b21603ea9a867ba513e2a667b08fbc6d80dd8..557cf822002663b7957194610d103210b159e5c4 100644
> --- a/fs/nfs/netns.h
> +++ b/fs/nfs/netns.h
> @@ -31,7 +31,11 @@ struct nfs_net {
> unsigned short nfs_callback_tcpport;
> unsigned short nfs_callback_tcpport6;
> int cb_users[NFS4_MAX_MINOR_VERSION + 1];
> -#endif
> +#if IS_ENABLED(CONFIG_NFS_V4_1)
> + struct list_head nfs4_data_server_cache;
> + spinlock_t nfs4_data_server_lock;
> +#endif /* CONFIG_NFS_V4_1 */
> +#endif /* CONFIG_NFS_V4 */
> struct nfs_netns_client *nfs_client;
> spinlock_t nfs_client_lock;
> ktime_t boot_time;
> diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
> index 2ee20a0f0b36d3b38e35c4cad966b9d58fa822f4..91ef486f40b943a1dc55164e610378ef73781e55 100644
> --- a/fs/nfs/pnfs_nfs.c
> +++ b/fs/nfs/pnfs_nfs.c
> @@ -16,6 +16,7 @@
> #include "nfs4session.h"
> #include "internal.h"
> #include "pnfs.h"
> +#include "netns.h"
>
> #define NFSDBG_FACILITY NFSDBG_PNFS
>
> @@ -504,14 +505,14 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist);
> /*
> * Data server cache
> *
> - * Data servers can be mapped to different device ids.
> - * nfs4_pnfs_ds reference counting
> + * Data servers can be mapped to different device ids, but should
> + * never be shared between net namespaces.
> + *
> + * nfs4_pnfs_ds reference counting:
> * - set to 1 on allocation
> * - incremented when a device id maps a data server already in the cache.
> * - decremented when deviceid is removed from the cache.
> */
> -static DEFINE_SPINLOCK(nfs4_ds_cache_lock);
> -static LIST_HEAD(nfs4_data_server_cache);
>
> /* Debug routines */
> static void
> @@ -604,12 +605,12 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
> * Lookup DS by addresses. nfs4_ds_cache_lock is held
> */
> static struct nfs4_pnfs_ds *
> -_data_server_lookup_locked(const struct net *net, const struct list_head *dsaddrs)
> +_data_server_lookup_locked(const struct nfs_net *nn, const struct list_head *dsaddrs)
> {
> struct nfs4_pnfs_ds *ds;
>
> - list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
> - if (ds->ds_net == net && _same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
> + list_for_each_entry(ds, &nn->nfs4_data_server_cache, ds_node)
> + if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
> return ds;
> return NULL;
> }
> @@ -653,10 +654,11 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds)
>
> void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds)
> {
> - if (refcount_dec_and_lock(&ds->ds_count,
> - &nfs4_ds_cache_lock)) {
> + struct nfs_net *nn = net_generic(ds->ds_net, nfs_net_id);
> +
> + if (refcount_dec_and_lock(&ds->ds_count, &nn->nfs4_data_server_lock)) {
> list_del_init(&ds->ds_node);
> - spin_unlock(&nfs4_ds_cache_lock);
> + spin_unlock(&nn->nfs4_data_server_lock);
> destroy_ds(ds);
> }
> }
> @@ -718,6 +720,7 @@ nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)
> struct nfs4_pnfs_ds *
> nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flags)
> {
> + struct nfs_net *nn = net_generic(net, nfs_net_id);
> struct nfs4_pnfs_ds *tmp_ds, *ds = NULL;
> char *remotestr;
>
> @@ -733,8 +736,8 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla
> /* this is only used for debugging, so it's ok if its NULL */
> remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags);
>
> - spin_lock(&nfs4_ds_cache_lock);
> - tmp_ds = _data_server_lookup_locked(net, dsaddrs);
> + spin_lock(&nn->nfs4_data_server_lock);
> + tmp_ds = _data_server_lookup_locked(nn, dsaddrs);
> if (tmp_ds == NULL) {
> INIT_LIST_HEAD(&ds->ds_addrs);
> list_splice_init(dsaddrs, &ds->ds_addrs);
> @@ -743,7 +746,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla
> INIT_LIST_HEAD(&ds->ds_node);
> ds->ds_net = net;
> ds->ds_clp = NULL;
> - list_add(&ds->ds_node, &nfs4_data_server_cache);
> + list_add(&ds->ds_node, &nn->nfs4_data_server_cache);
> dprintk("%s add new data server %s\n", __func__,
> ds->ds_remotestr);
> } else {
> @@ -755,7 +758,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla
> refcount_read(&tmp_ds->ds_count));
> ds = tmp_ds;
> }
> - spin_unlock(&nfs4_ds_cache_lock);
> + spin_unlock(&nn->nfs4_data_server_lock);
> out:
> return ds;
> }
>
next prev parent reply other threads:[~2025-04-10 19:39 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-10 18:12 [PATCH 0/2] nfs: don't share pNFS DS connections between net namespaces Jeff Layton
2025-04-10 18:12 ` [PATCH 1/2] " Jeff Layton
2025-04-10 18:12 ` [PATCH 2/2] nfs: move the nfs4_data_server_cache into struct nfs_net Jeff Layton
2025-04-10 19:39 ` Anna Schumaker [this message]
2025-04-10 19:57 ` 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=64123840-4fd7-4d76-ae99-c92138d20a4a@oracle.com \
--to=anna.schumaker@oracle.com \
--cc=anna@kernel.org \
--cc=jlayton@kernel.org \
--cc=linux-kernel@vger.keornel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=osandov@osandov.com \
--cc=sargun@sargun.me \
--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