Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Jeff Layton and committed by
Trond Myklebust
d5fb22a7 6b9785dc

+29 -15
+7
fs/nfs/client.c
··· 1200 1200 #if IS_ENABLED(CONFIG_NFS_V4) 1201 1201 idr_init(&nn->cb_ident_idr); 1202 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); 1206 + #endif 1203 1207 spin_lock_init(&nn->nfs_client_lock); 1204 1208 nn->boot_time = ktime_get_real(); 1205 1209 memset(&nn->rpcstats, 0, sizeof(nn->rpcstats)); ··· 1220 1216 nfs_cleanup_cb_ident_idr(net); 1221 1217 WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); 1222 1218 WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); 1219 + #if IS_ENABLED(CONFIG_NFS_V4_1) 1220 + WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache)); 1221 + #endif 1223 1222 } 1224 1223 1225 1224 #ifdef CONFIG_PROC_FS
+5 -1
fs/nfs/netns.h
··· 31 31 unsigned short nfs_callback_tcpport; 32 32 unsigned short nfs_callback_tcpport6; 33 33 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 */ 35 39 struct nfs_netns_client *nfs_client; 36 40 spinlock_t nfs_client_lock; 37 41 ktime_t boot_time;
+17 -14
fs/nfs/pnfs_nfs.c
··· 16 16 #include "nfs4session.h" 17 17 #include "internal.h" 18 18 #include "pnfs.h" 19 + #include "netns.h" 19 20 20 21 #define NFSDBG_FACILITY NFSDBG_PNFS 21 22 ··· 505 504 /* 506 505 * Data server cache 507 506 * 508 - * Data servers can be mapped to different device ids. 509 - * nfs4_pnfs_ds reference counting 507 + * Data servers can be mapped to different device ids, but should 508 + * never be shared between net namespaces. 509 + * 510 + * nfs4_pnfs_ds reference counting: 510 511 * - set to 1 on allocation 511 512 * - incremented when a device id maps a data server already in the cache. 512 513 * - decremented when deviceid is removed from the cache. 513 514 */ 514 - static DEFINE_SPINLOCK(nfs4_ds_cache_lock); 515 - static LIST_HEAD(nfs4_data_server_cache); 516 515 517 516 /* Debug routines */ 518 517 static void ··· 605 604 * Lookup DS by addresses. nfs4_ds_cache_lock is held 606 605 */ 607 606 static struct nfs4_pnfs_ds * 608 - _data_server_lookup_locked(const struct net *net, const struct list_head *dsaddrs) 607 + _data_server_lookup_locked(const struct nfs_net *nn, const struct list_head *dsaddrs) 609 608 { 610 609 struct nfs4_pnfs_ds *ds; 611 610 612 - list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) 613 - if (ds->ds_net == net && _same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) 611 + list_for_each_entry(ds, &nn->nfs4_data_server_cache, ds_node) 612 + if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) 614 613 return ds; 615 614 return NULL; 616 615 } ··· 654 653 655 654 void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds) 656 655 { 657 - if (refcount_dec_and_lock(&ds->ds_count, 658 - &nfs4_ds_cache_lock)) { 656 + struct nfs_net *nn = net_generic(ds->ds_net, nfs_net_id); 657 + 658 + if (refcount_dec_and_lock(&ds->ds_count, &nn->nfs4_data_server_lock)) { 659 659 list_del_init(&ds->ds_node); 660 - spin_unlock(&nfs4_ds_cache_lock); 660 + spin_unlock(&nn->nfs4_data_server_lock); 661 661 destroy_ds(ds); 662 662 } 663 663 } ··· 720 718 struct nfs4_pnfs_ds * 721 719 nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_flags) 722 720 { 721 + struct nfs_net *nn = net_generic(net, nfs_net_id); 723 722 struct nfs4_pnfs_ds *tmp_ds, *ds = NULL; 724 723 char *remotestr; 725 724 ··· 736 733 /* this is only used for debugging, so it's ok if its NULL */ 737 734 remotestr = nfs4_pnfs_remotestr(dsaddrs, gfp_flags); 738 735 739 - spin_lock(&nfs4_ds_cache_lock); 740 - tmp_ds = _data_server_lookup_locked(net, dsaddrs); 736 + spin_lock(&nn->nfs4_data_server_lock); 737 + tmp_ds = _data_server_lookup_locked(nn, dsaddrs); 741 738 if (tmp_ds == NULL) { 742 739 INIT_LIST_HEAD(&ds->ds_addrs); 743 740 list_splice_init(dsaddrs, &ds->ds_addrs); ··· 746 743 INIT_LIST_HEAD(&ds->ds_node); 747 744 ds->ds_net = net; 748 745 ds->ds_clp = NULL; 749 - list_add(&ds->ds_node, &nfs4_data_server_cache); 746 + list_add(&ds->ds_node, &nn->nfs4_data_server_cache); 750 747 dprintk("%s add new data server %s\n", __func__, 751 748 ds->ds_remotestr); 752 749 } else { ··· 758 755 refcount_read(&tmp_ds->ds_count)); 759 756 ds = tmp_ds; 760 757 } 761 - spin_unlock(&nfs4_ds_cache_lock); 758 + spin_unlock(&nn->nfs4_data_server_lock); 762 759 out: 763 760 return ds; 764 761 }