Skip to content

Commit d5fb22a

Browse files
jtlaytonTrond Myklebust
authored andcommitted
nfs: move the nfs4_data_server_cache into struct nfs_net
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> Reviewed-by: Benjamin Coddington <bcodding@redhat.com> Link: https://lore.kernel.org/r/20250410-nfs-ds-netns-v2-2-f80b7979ba80@kernel.org Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 6b9785d commit d5fb22a

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

fs/nfs/client.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,10 @@ void nfs_clients_init(struct net *net)
11991199
INIT_LIST_HEAD(&nn->nfs_volume_list);
12001200
#if IS_ENABLED(CONFIG_NFS_V4)
12011201
idr_init(&nn->cb_ident_idr);
1202+
#endif
1203+
#if IS_ENABLED(CONFIG_NFS_V4_1)
1204+
INIT_LIST_HEAD(&nn->nfs4_data_server_cache);
1205+
spin_lock_init(&nn->nfs4_data_server_lock);
12021206
#endif
12031207
spin_lock_init(&nn->nfs_client_lock);
12041208
nn->boot_time = ktime_get_real();
@@ -1216,6 +1220,9 @@ void nfs_clients_exit(struct net *net)
12161220
nfs_cleanup_cb_ident_idr(net);
12171221
WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
12181222
WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
1223+
#if IS_ENABLED(CONFIG_NFS_V4_1)
1224+
WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache));
1225+
#endif
12191226
}
12201227

12211228
#ifdef CONFIG_PROC_FS

fs/nfs/netns.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ struct nfs_net {
3131
unsigned short nfs_callback_tcpport;
3232
unsigned short nfs_callback_tcpport6;
3333
int cb_users[NFS4_MAX_MINOR_VERSION + 1];
34-
#endif
34+
#endif /* CONFIG_NFS_V4 */
35+
#if IS_ENABLED(CONFIG_NFS_V4_1)
36+
struct list_head nfs4_data_server_cache;
37+
spinlock_t nfs4_data_server_lock;
38+
#endif /* CONFIG_NFS_V4_1 */
3539
struct nfs_netns_client *nfs_client;
3640
spinlock_t nfs_client_lock;
3741
ktime_t boot_time;

fs/nfs/pnfs_nfs.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "nfs4session.h"
1717
#include "internal.h"
1818
#include "pnfs.h"
19+
#include "netns.h"
1920

2021
#define NFSDBG_FACILITY NFSDBG_PNFS
2122

@@ -504,14 +505,14 @@ EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist);
504505
/*
505506
* Data server cache
506507
*
507-
* Data servers can be mapped to different device ids.
508-
* nfs4_pnfs_ds reference counting
508+
* Data servers can be mapped to different device ids, but should
509+
* never be shared between net namespaces.
510+
*
511+
* nfs4_pnfs_ds reference counting:
509512
* - set to 1 on allocation
510513
* - incremented when a device id maps a data server already in the cache.
511514
* - decremented when deviceid is removed from the cache.
512515
*/
513-
static DEFINE_SPINLOCK(nfs4_ds_cache_lock);
514-
static LIST_HEAD(nfs4_data_server_cache);
515516

516517
/* Debug routines */
517518
static void
@@ -604,12 +605,12 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1,
604605
* Lookup DS by addresses. nfs4_ds_cache_lock is held
605606
*/
606607
static struct nfs4_pnfs_ds *
607-
_data_server_lookup_locked(const struct net *net, const struct list_head *dsaddrs)
608+
_data_server_lookup_locked(const struct nfs_net *nn, const struct list_head *dsaddrs)
608609
{
609610
struct nfs4_pnfs_ds *ds;
610611

611-
list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
612-
if (ds->ds_net == net && _same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
612+
list_for_each_entry(ds, &nn->nfs4_data_server_cache, ds_node)
613+
if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs))
613614
return ds;
614615
return NULL;
615616
}
@@ -653,10 +654,11 @@ static void destroy_ds(struct nfs4_pnfs_ds *ds)
653654

654655
void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds)
655656
{
656-
if (refcount_dec_and_lock(&ds->ds_count,
657-
&nfs4_ds_cache_lock)) {
657+
struct nfs_net *nn = net_generic(ds->ds_net, nfs_net_id);
658+
659+
if (refcount_dec_and_lock(&ds->ds_count, &nn->nfs4_data_server_lock)) {
658660
list_del_init(&ds->ds_node);
659-
spin_unlock(&nfs4_ds_cache_lock);
661+
spin_unlock(&nn->nfs4_data_server_lock);
660662
destroy_ds(ds);
661663
}
662664
}
@@ -718,6 +720,7 @@ nfs4_pnfs_remotestr(struct list_head *dsaddrs, gfp_t gfp_flags)
718720
struct nfs4_pnfs_ds *
719721
nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flags)
720722
{
723+
struct nfs_net *nn = net_generic(net, nfs_net_id);
721724
struct nfs4_pnfs_ds *tmp_ds, *ds = NULL;
722725
char *remotestr;
723726

@@ -733,8 +736,8 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla
733736
/* this is only used for debugging, so it's ok if its NULL */
734737
remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags);
735738

736-
spin_lock(&nfs4_ds_cache_lock);
737-
tmp_ds = _data_server_lookup_locked(net, dsaddrs);
739+
spin_lock(&nn->nfs4_data_server_lock);
740+
tmp_ds = _data_server_lookup_locked(nn, dsaddrs);
738741
if (tmp_ds == NULL) {
739742
INIT_LIST_HEAD(&ds->ds_addrs);
740743
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
743746
INIT_LIST_HEAD(&ds->ds_node);
744747
ds->ds_net = net;
745748
ds->ds_clp = NULL;
746-
list_add(&ds->ds_node, &nfs4_data_server_cache);
749+
list_add(&ds->ds_node, &nn->nfs4_data_server_cache);
747750
dprintk("%s add new data server %s\n", __func__,
748751
ds->ds_remotestr);
749752
} else {
@@ -755,7 +758,7 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla
755758
refcount_read(&tmp_ds->ds_count));
756759
ds = tmp_ds;
757760
}
758-
spin_unlock(&nfs4_ds_cache_lock);
761+
spin_unlock(&nn->nfs4_data_server_lock);
759762
out:
760763
return ds;
761764
}

0 commit comments

Comments
 (0)