[PATCH] nfsd: Make NFS client_id increment atomic to avoid race condition

From: Muhammad Asim Zahid
Date: Fri Mar 15 2024 - 08:44:44 EST


The following log messages show conflict in clientid
[err] kernel: [ 16.228090] NFS: Server fct reports our clientid is in use
[warning] kernel: [ 16.228102] NFS: state manager: lease expired failed on NFSv4 server fct with error 1
[warning] kernel: [ 16.228102] NFS: state manager: lease expired failed on NFSv4 server fct with error 1

The increment to client_verifier counter and client_id counter is
set to atomic so as to avoid race condition which causes the
aforementioned error.

Change-Id: Ic0fa8c14a8bba043ae8882f6750f512bb5f3aac1
---
fs/nfsd/netns.h | 4 ++--
fs/nfsd/nfs4state.c | 4 ++--
fs/nfsd/nfsctl.c | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 935c1028c217..67b5aa1516e2 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -119,8 +119,8 @@ struct nfsd_net {
unsigned int max_connections;

u32 clientid_base;
- u32 clientid_counter;
- u32 clverifier_counter;
+ atomic_t clientid_counter;
+ atomic_t clverifier_counter;

struct svc_serv *nfsd_serv;

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9b660491f393..d67a6a593f59 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2321,14 +2321,14 @@ static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn)
* __force to keep sparse happy
*/
verf[0] = (__force __be32)(u32)ktime_get_real_seconds();
- verf[1] = (__force __be32)nn->clverifier_counter++;
+ verf[1] = (__force __be32)atomic_inc_return(&(nn->clverifier_counter));
memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data));
}

static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn)
{
clp->cl_clientid.cl_boot = (u32)nn->boot_time;
- clp->cl_clientid.cl_id = nn->clientid_counter++;
+ clp->cl_clientid.cl_id = atomic_inc_return(&(nn->clientid_counter));
gen_confirm(clp, nn);
}

diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index cb73c1292562..a9ef86ee7250 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1481,10 +1481,10 @@ static __net_init int nfsd_init_net(struct net *net)
nn->nfsd4_grace = 90;
nn->somebody_reclaimed = false;
nn->track_reclaim_completes = false;
- nn->clverifier_counter = prandom_u32();
+ atomic_set(&(nn->clverifier_counter), prandom_u32());
nn->clientid_base = prandom_u32();
- nn->clientid_counter = nn->clientid_base + 1;
- nn->s2s_cp_cl_id = nn->clientid_counter++;
+ atomic_set(&(nn->clientid_counter), nn->clientid_base + 1);
+ nn->s2s_cp_cl_id = atomic_inc_return(&(nn->clientid_counter));

atomic_set(&nn->ntf_refcnt, 0);
init_waitqueue_head(&nn->ntf_wq);
--
2.42.0