[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <ZfRbWx8L9WJGKa_k@manet.1015granger.net>
Date: Fri, 15 Mar 2024 10:29:47 -0400
From: Chuck Lever <chuck.lever@...cle.com>
To: Muhammad Asim Zahid <muhammad.zahid@...ia.com>
Cc: "J. Bruce Fields" <bfields@...ldses.org>, linux-nfs@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH] nfsd: Make NFS client_id increment atomic to avoid race
condition
On Fri, Mar 15, 2024 at 01:39:57PM +0100, Muhammad Asim Zahid wrote:
> 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.
These client messages are in response to NFS4ERR_CLID_INUSE. This
condition is not because the server did not increment the client ID.
It's because there actually is another client (possibly more than
one) using the same clientid string and authentication principal.
Refer to:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/nfs/client-identifier.rst
> 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
>
--
Chuck Lever
Powered by blists - more mailing lists