[PATCH 19/21] NFSv4/pnfs: Re-home the data-server cache onto hash buckets
Benjamin Coddington <[email protected]>
| Newsgroups | org.kernel.vger.linux-nfs |
|---|---|
| Message-ID | <844b2583b5d0dd08575909b9dae7fdfe804c73ad.1786653063.git.bcodding@hammerspace.com> |
Mechanical conversion of the per-net data-server cache from a single list_head to an array of hlist buckets: nfs4_pnfs_ds.ds_node becomes an hlist_node, netns init/teardown cover every bucket, and removal uses hlist_del_init (which needs no bucket reference). Insertion still targets bucket 0 and lookup still scans every entry, so behavior and cost are unchanged -- keying the buckets by the DS address set comes next. Splitting the structural churn from the keying keeps a bisect able to tell a list-conversion bug from a hash-key bug. Assisted-by: Claude:claude-fable-5 Signed-off-by: Benjamin Coddington <[email protected]> --- fs/nfs/client.c | 6 ++++-- fs/nfs/netns.h | 5 ++++- fs/nfs/pnfs.h | 2 +- fs/nfs/pnfs_nfs.c | 17 ++++++++++------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4dcb91ab3039..10eeb14d251b 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -1283,7 +1283,8 @@ 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); - INIT_LIST_HEAD(&nn->nfs4_data_server_cache); + for (int i = 0; i < NFS4_DS_CACHE_HASH_SIZE; i++) + INIT_HLIST_HEAD(&nn->nfs4_data_server_cache[i]); spin_lock_init(&nn->nfs4_data_server_lock); #endif /* CONFIG_NFS_V4 */ spin_lock_init(&nn->nfs_client_lock); @@ -1303,7 +1304,8 @@ void nfs_clients_exit(struct net *net) WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); #if IS_ENABLED(CONFIG_NFS_V4) - WARN_ON_ONCE(!list_empty(&nn->nfs4_data_server_cache)); + for (int i = 0; i < NFS4_DS_CACHE_HASH_SIZE; i++) + WARN_ON_ONCE(!hlist_empty(&nn->nfs4_data_server_cache[i])); #endif /* CONFIG_NFS_V4 */ } diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 36658579100d..f21118554272 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -31,7 +31,10 @@ struct nfs_net { unsigned short nfs_callback_tcpport; unsigned short nfs_callback_tcpport6; int cb_users[NFS4_MAX_MINOR_VERSION + 1]; - struct list_head nfs4_data_server_cache; +#define NFS4_DS_CACHE_HASH_BITS 8 +#define NFS4_DS_CACHE_HASH_SIZE (1 << NFS4_DS_CACHE_HASH_BITS) + /* hashed by nfs4_ds_addrs_hash() over the DS's address set */ + struct hlist_head nfs4_data_server_cache[NFS4_DS_CACHE_HASH_SIZE]; spinlock_t nfs4_data_server_lock; #endif /* CONFIG_NFS_V4 */ struct nfs_netns_client *nfs_client; diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 1ce1cbc32f77..e0a7ae5fe8e9 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -57,7 +57,7 @@ struct nfs4_pnfs_ds_addr { }; struct nfs4_pnfs_ds { - struct list_head ds_node; /* nfs4_pnfs_dev_hlist dev_dslist */ + struct hlist_node ds_node; /* nfs_net nfs4_data_server_cache */ char *ds_remotestr; /* comma sep list of addrs */ struct list_head ds_addrs; const struct net *ds_net; diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index f40368f839d0..e15e0059c56b 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c @@ -604,16 +604,19 @@ _same_data_server_addrs_locked(const struct list_head *dsaddrs1, } /* - * Lookup DS by addresses. nfs4_ds_cache_lock is held + * Lookup DS by addresses. nfs4_data_server_lock is held */ static struct nfs4_pnfs_ds * _data_server_lookup_locked(const struct nfs_net *nn, const struct list_head *dsaddrs) { struct nfs4_pnfs_ds *ds; - list_for_each_entry(ds, &nn->nfs4_data_server_cache, ds_node) - if (_same_data_server_addrs_locked(&ds->ds_addrs, dsaddrs)) - return ds; + for (int i = 0; i < NFS4_DS_CACHE_HASH_SIZE; i++) + hlist_for_each_entry(ds, &nn->nfs4_data_server_cache[i], + ds_node) + if (_same_data_server_addrs_locked(&ds->ds_addrs, + dsaddrs)) + return ds; return NULL; } @@ -659,7 +662,7 @@ void nfs4_pnfs_ds_put(struct nfs4_pnfs_ds *ds) 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); + hlist_del_init(&ds->ds_node); spin_unlock(&nn->nfs4_data_server_lock); destroy_ds(ds); } @@ -745,10 +748,10 @@ nfs4_pnfs_ds_add(const struct net *net, struct list_head *dsaddrs, gfp_t gfp_fla list_splice_init(dsaddrs, &ds->ds_addrs); ds->ds_remotestr = remotestr; refcount_set(&ds->ds_count, 1); - INIT_LIST_HEAD(&ds->ds_node); + INIT_HLIST_NODE(&ds->ds_node); ds->ds_net = net; ds->ds_clp = NULL; - list_add(&ds->ds_node, &nn->nfs4_data_server_cache); + hlist_add_head(&ds->ds_node, &nn->nfs4_data_server_cache[0]); dprintk("%s add new data server %s\n", __func__, ds->ds_remotestr); } else { -- 2.53.0