From: Mike Snitzer <snitzer@kernel.org>
To: NeilBrown <neil@brown.name>
Cc: "Trond Myklebust" <trondmy@kernel.org>,
"Anna Schumaker" <anna@kernel.org>,
"Pali Rohár" <pali@kernel.org>,
"Vincent Mailhol" <mailhol.vincent@wanadoo.fr>,
"Chuck Lever" <chuck.lever@oracle.com>,
"Jeff Layton" <jlayton@kernel.org>,
linux-nfs@vger.kernel.org
Subject: Re: [PATCH 1/6] nfs_localio: use cmpxchg() to install new nfs_file_localio
Date: Wed, 30 Apr 2025 18:21:04 -0400 [thread overview]
Message-ID: <aBKiUDGk4qifnKa2@kernel.org> (raw)
In-Reply-To: <20250430040429.2743921-2-neil@brown.name>
On Wed, Apr 30, 2025 at 02:01:11PM +1000, NeilBrown wrote:
> Rather than using nfs_uuid.lock to protect installing
> a new ro_file or rw_file, change to use cmpxchg().
> Removing the file already uses xchg() so this improves symmetry
> and also makes the code a little simpler.
>
> Also remove the optimisation of not taking the lock, and not removing
> the nfs_file_localio from the linked list, when both ->ro_file and
> ->rw_file are already NULL. Given that ->nfs_uuid was not NULL, it is
> extremely unlikely that neither ->ro_file or ->rw_file is NULL so
> this optimisation can be of little value and it complicates
> understanding of the code - why can the list_del_init() be skipped?
>
> Finally, move the assignment of NULL to ->nfs_uuid until after
> the last action on the nfs_file_localio (the list_del_init). As soon as
> this is NULL a racing nfs_close_local_fh() can bypass all the locking
> and go on to free the nfs_file_localio, so we must be certain to be
> finished with it first.
>
> Fixes: 86e00412254a ("nfs: cache all open LOCALIO nfsd_file(s) in client")
> Signed-off-by: NeilBrown <neil@brown.name>
> ---
> fs/nfs/localio.c | 11 +++--------
> fs/nfs_common/nfslocalio.c | 36 ++++++++++++++++--------------------
> 2 files changed, 19 insertions(+), 28 deletions(-)
>
> diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
> index 5c21caeae075..3674dd86f095 100644
> --- a/fs/nfs/localio.c
> +++ b/fs/nfs/localio.c
> @@ -279,14 +279,9 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
> if (IS_ERR(new))
> return NULL;
> /* try to swap in the pointer */
> - spin_lock(&clp->cl_uuid.lock);
> - nf = rcu_dereference_protected(*pnf, 1);
> - if (!nf) {
> - nf = new;
> - new = NULL;
> - rcu_assign_pointer(*pnf, nf);
> - }
> - spin_unlock(&clp->cl_uuid.lock);
> + nf = unrcu_pointer(cmpxchg(pnf, NULL, RCU_INITIALIZER(new)));
> + if (!nf)
> + swap(nf, new);
> rcu_read_lock();
> }
> nf = nfs_local_file_get(nf);
> diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c
> index 6a0bdea6d644..d72eecb85ea9 100644
> --- a/fs/nfs_common/nfslocalio.c
> +++ b/fs/nfs_common/nfslocalio.c
> @@ -285,28 +285,24 @@ void nfs_close_local_fh(struct nfs_file_localio *nfl)
> return;
> }
>
> - ro_nf = rcu_access_pointer(nfl->ro_file);
> - rw_nf = rcu_access_pointer(nfl->rw_file);
> - if (ro_nf || rw_nf) {
> - spin_lock(&nfs_uuid->lock);
> - if (ro_nf)
> - ro_nf = rcu_dereference_protected(xchg(&nfl->ro_file, NULL), 1);
> - if (rw_nf)
> - rw_nf = rcu_dereference_protected(xchg(&nfl->rw_file, NULL), 1);
> -
> - /* Remove nfl from nfs_uuid->files list */
> - RCU_INIT_POINTER(nfl->nfs_uuid, NULL);
> - list_del_init(&nfl->list);
> - spin_unlock(&nfs_uuid->lock);
> - rcu_read_unlock();
> + ro_nf = unrcu_pointer(xchg(&nfl->ro_file, NULL));
> + rw_nf = unrcu_pointer(xchg(&nfl->rw_file, NULL));
>
> - if (ro_nf)
> - nfs_to_nfsd_file_put_local(ro_nf);
> - if (rw_nf)
> - nfs_to_nfsd_file_put_local(rw_nf);
> - return;
> - }
> + spin_lock(&nfs_uuid->lock);
> + /* Remove nfl from nfs_uuid->files list */
> + list_del_init(&nfl->list);
> + spin_unlock(&nfs_uuid->lock);
> rcu_read_unlock();
> + /* Now we can allow racing nfs_close_local_fh() to
> + * skip the locking.
> + */
> + RCU_INIT_POINTER(nfl->nfs_uuid, NULL);
> +
> + if (ro_nf)
> + nfs_to_nfsd_file_put_local(ro_nf);
> + if (rw_nf)
> + nfs_to_nfsd_file_put_local(rw_nf);
> + return;
> }
This return at the end of the function isn't needed.
> EXPORT_SYMBOL_GPL(nfs_close_local_fh);
>
> --
> 2.49.0
>
>
next prev parent reply other threads:[~2025-04-30 22:21 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-30 4:01 [PATCH 0/6] nfs_localio: fixes for races and errors from older compilers NeilBrown
2025-04-30 4:01 ` [PATCH 1/6] nfs_localio: use cmpxchg() to install new nfs_file_localio NeilBrown
2025-04-30 22:21 ` Mike Snitzer [this message]
2025-04-30 4:01 ` [PATCH 2/6] nfs_localio: always hold nfsd net ref with nfsd_file ref NeilBrown
2025-04-30 4:01 ` [PATCH 3/6] nfs_localio: simplify interface to nfsd for getting nfsd_file NeilBrown
2025-04-30 4:01 ` [PATCH 4/6] nfs_localio: change nfsd_file_put_local() to take a pointer to __rcu struct NeilBrown
2025-04-30 4:01 ` [PATCH 5/6] nfs_localio: duplicate nfs_close_local_fh() NeilBrown
2025-04-30 4:01 ` [PATCH 6/6] nfs_localio: protect race between nfs_uuid_put() and nfs_close_local_fh() NeilBrown
2025-04-30 17:34 ` Mike Snitzer
2025-04-30 20:20 ` Mike Snitzer
2025-04-30 22:16 ` NeilBrown
2025-04-30 22:12 ` NeilBrown
-- strict thread matches above, loose matches on Subject: below --
2025-05-09 0:46 [PATCH 0/6 v2] nfs_localio: fixes for races and errors from older compilers NeilBrown
2025-05-09 0:46 ` [PATCH 1/6] nfs_localio: use cmpxchg() to install new nfs_file_localio NeilBrown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aBKiUDGk4qifnKa2@kernel.org \
--to=snitzer@kernel.org \
--cc=anna@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=jlayton@kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=mailhol.vincent@wanadoo.fr \
--cc=neil@brown.name \
--cc=pali@kernel.org \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox