From: Mike Snitzer <snitzer@kernel.org>
To: NeilBrown <neilb@suse.de>
Cc: linux-nfs@vger.kernel.org, Anna Schumaker <anna@kernel.org>,
Trond Myklebust <trondmy@hammerspace.com>,
Chuck Lever <chuck.lever@oracle.com>,
Jeff Layton <jlayton@kernel.org>
Subject: Re: [for-6.13 PATCH v2 06/15] nfs: cache all open LOCALIO nfsd_file(s) in client
Date: Fri, 15 Nov 2024 11:49:08 -0500 [thread overview]
Message-ID: <Zzd7hKl5_cu4yP2s@kernel.org> (raw)
In-Reply-To: <173164036674.1734440.14888275520804852973@noble.neil.brown.name>
On Fri, Nov 15, 2024 at 02:12:46PM +1100, NeilBrown wrote:
> On Thu, 14 Nov 2024, Mike Snitzer wrote:
> > This commit switches from leaning heavily on NFSD's filecache (in
> > terms of GC'd nfsd_files) back to caching nfsd_files in the
> > client. A later commit will add the callback mechanism needed to
> > allow NFSD to force the NFS client to cleanup all caches files.
> >
> > Add nfs_fh_localio_init() and 'struct nfs_fh_localio' to cache opened
> > nfsd_file(s) (both a RO and RW nfsd_file is able to be opened and
> > cached for a given nfs_fh).
> >
> > Update nfs_local_open_fh() to cache the nfsd_file once it is opened
> > using __nfs_local_open_fh().
> >
> > Introduce nfs_close_local_fh() to clear the cached open nfsd_files and
> > call nfs_to_nfsd_file_put_local().
> >
> > Refcounting is such that:
> > - nfs_local_open_fh() is paired with nfs_close_local_fh().
> > - __nfs_local_open_fh() is paired with nfs_to_nfsd_file_put_local().
> > - nfs_local_file_get() is paired with nfs_local_file_put().
> >
> > Signed-off-by: Mike Snitzer <snitzer@kernel.org>
> > ---
> > fs/nfs/flexfilelayout/flexfilelayout.c | 29 +++++----
> > fs/nfs/flexfilelayout/flexfilelayout.h | 1 +
> > fs/nfs/inode.c | 3 +
> > fs/nfs/internal.h | 4 +-
> > fs/nfs/localio.c | 89 +++++++++++++++++++++-----
> > fs/nfs/pagelist.c | 5 +-
> > fs/nfs/write.c | 3 +-
> > fs/nfs_common/nfslocalio.c | 52 ++++++++++++++-
> > include/linux/nfs_fs.h | 22 ++++++-
> > include/linux/nfslocalio.h | 18 +++---
> > 10 files changed, 181 insertions(+), 45 deletions(-)
> >
> > diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
> > index f78115c6c2c12..451f168d882be 100644
> > --- a/fs/nfs/flexfilelayout/flexfilelayout.c
> > +++ b/fs/nfs/flexfilelayout/flexfilelayout.c
> > @@ -164,18 +164,17 @@ decode_name(struct xdr_stream *xdr, u32 *id)
> > }
> >
> > static struct nfsd_file *
> > -ff_local_open_fh(struct nfs_client *clp, const struct cred *cred,
> > +ff_local_open_fh(struct pnfs_layout_segment *lseg, u32 ds_idx,
> > + struct nfs_client *clp, const struct cred *cred,
> > struct nfs_fh *fh, fmode_t mode)
> > {
> > - if (mode & FMODE_WRITE) {
> > - /*
> > - * Always request read and write access since this corresponds
> > - * to a rw layout.
> > - */
> > - mode |= FMODE_READ;
> > - }
> > +#if IS_ENABLED(CONFIG_NFS_LOCALIO)
> > + struct nfs4_ff_layout_mirror *mirror = FF_LAYOUT_COMP(lseg, ds_idx);
> >
> > - return nfs_local_open_fh(clp, cred, fh, mode);
> > + return nfs_local_open_fh(clp, cred, fh, &mirror->nfl, mode);
> > +#else
> > + return NULL;
> > +#endif
> > }
> >
> > static bool ff_mirror_match_fh(const struct nfs4_ff_layout_mirror *m1,
> > @@ -247,6 +246,9 @@ static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags)
> > spin_lock_init(&mirror->lock);
> > refcount_set(&mirror->ref, 1);
> > INIT_LIST_HEAD(&mirror->mirrors);
> > +#if IS_ENABLED(CONFIG_NFS_LOCALIO)
> > + nfs_localio_file_init(&mirror->nfl);
> > +#endif
>
> Can we make nfs_localio_file_init() a #define in the no-NFS_LOCALIO
> case, we don't need the #if.
> (every time you write #if in a .c file think to your self "Neil will
> hate this". See also coding-style.rst. 21) Conditional Compilation.
It already was defined in header, and doesn't need wrapping in caller,
I just mistakenly wrapped it again in ff_layout_alloc_mirror().
Fixed.
> > }
> > return mirror;
> > }
> > @@ -257,6 +259,9 @@ static void ff_layout_free_mirror(struct nfs4_ff_layout_mirror *mirror)
> >
> > ff_layout_remove_mirror(mirror);
> > kfree(mirror->fh_versions);
> > +#if IS_ENABLED(CONFIG_NFS_LOCALIO)
> > + nfs_close_local_fh(&mirror->nfl);
> > +#endif
> > cred = rcu_access_pointer(mirror->ro_cred);
> > put_cred(cred);
> > cred = rcu_access_pointer(mirror->rw_cred);
I fixed this call to nfs_close_local_fh() to not use #if also.
> > diff --git a/fs/nfs/flexfilelayout/flexfilelayout.h b/fs/nfs/flexfilelayout/flexfilelayout.h
> > index f84b3fb0dddd8..095df09017a57 100644
> > --- a/fs/nfs/flexfilelayout/flexfilelayout.h
> > +++ b/fs/nfs/flexfilelayout/flexfilelayout.h
> > @@ -83,6 +83,7 @@ struct nfs4_ff_layout_mirror {
> > nfs4_stateid stateid;
> > const struct cred __rcu *ro_cred;
> > const struct cred __rcu *rw_cred;
> > + struct nfs_file_localio nfl;
>
> This probably wants a #if around it though - it is in a .h after all.
I unconditionall defined 'struct nfs_file_localio' otherwise the
calls that access this nfl member (nfs_localio_file_init) _will_ need
special treatment.
>
> > refcount_t ref;
> > spinlock_t lock;
> > unsigned long flags;
<snip>
> > diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c
> > index abc132166742e..35a2e48731df6 100644
> > --- a/fs/nfs_common/nfslocalio.c
> > +++ b/fs/nfs_common/nfslocalio.c
> > @@ -151,9 +151,18 @@ void nfs_localio_invalidate_clients(struct list_head *cl_uuid_list)
> > }
> > EXPORT_SYMBOL_GPL(nfs_localio_invalidate_clients);
> >
> > +static void nfs_uuid_add_file(nfs_uuid_t *nfs_uuid, struct nfs_file_localio *nfl)
> > +{
> > + spin_lock(&nfs_uuid_lock);
> > + if (!nfl->nfs_uuid)
> > + rcu_assign_pointer(nfl->nfs_uuid, nfs_uuid);
> > + spin_unlock(&nfs_uuid_lock);
> > +}
> > +
> > struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
> > struct rpc_clnt *rpc_clnt, const struct cred *cred,
> > - const struct nfs_fh *nfs_fh, const fmode_t fmode)
> > + const struct nfs_fh *nfs_fh, struct nfs_file_localio *nfl,
> > + const fmode_t fmode)
> > {
> > struct net *net;
> > struct nfsd_file *localio;
> > @@ -180,11 +189,50 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
> > cred, nfs_fh, fmode);
> > if (IS_ERR(localio))
> > nfs_to_nfsd_net_put(net);
> > + else
> > + nfs_uuid_add_file(uuid, nfl);
> >
> > return localio;
> > }
> > EXPORT_SYMBOL_GPL(nfs_open_local_fh);
> >
> > +void nfs_close_local_fh(struct nfs_file_localio *nfl)
> > +{
> > + struct nfsd_file *ro_nf = NULL;
> > + struct nfsd_file *rw_nf = NULL;
> > + nfs_uuid_t *nfs_uuid;
> > +
> > + rcu_read_lock();
> > + nfs_uuid = rcu_dereference(nfl->nfs_uuid);
>
> nfl->nfs_uuid is a void*. Why do you assign it to an 'nfs_uuid_t *' ??
Yeah, I made it void* to not have to play games with nfs_uuid_t in
include/linux/nfs_fs.h
It is assigned to 'nfs_uuid_t *' because I dereference it to get its
spinlock in later patch (that splits the nfs_uuid_lock).
> And why do we need rcu here? We never dereference that pointer.
As I just said, I do in the patch that splits the nfs_uuid_lock.
And I made nfl->nfs_uuid management RCU protected given it being NULL
or not is significant and I'd rather not require other synchronization
via other locking.
SO while I appreciate your review here, the code in final form (once
nfs_uuid_lock lock split patch applied) does need RCU as I've written
it.
> I would just have
>
> if (!nfl->nfs_uuid || (!nfl->ro_file && !nfl->rw_file))
> return;
>
> then take the spinlock and do it the real work.
>
> > + if (!nfs_uuid) {
> > + /* regular (non-LOCALIO) NFS will hammer this */
> > + rcu_read_unlock();
> > + 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);
> > +
> > + rcu_assign_pointer(nfl->nfs_uuid, NULL);
> > + spin_unlock(&nfs_uuid_lock);
> > + rcu_read_unlock();
> > +
> > + if (ro_nf)
> > + nfs_to_nfsd_file_put_local(ro_nf);
> > + if (rw_nf)
> > + nfs_to_nfsd_file_put_local(rw_nf);
> > + return;
> > + }
> > + rcu_read_unlock();
> > +}
> > +EXPORT_SYMBOL_GPL(nfs_close_local_fh);
> > +
> > /*
> > * The NFS LOCALIO code needs to call into NFSD using various symbols,
> > * but cannot be statically linked, because that will make the NFS
> > diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> > index 039898d70954f..67ae2c3f41d20 100644
> > --- a/include/linux/nfs_fs.h
> > +++ b/include/linux/nfs_fs.h
> > @@ -77,6 +77,23 @@ struct nfs_lock_context {
> > struct rcu_head rcu_head;
> > };
> >
> > +struct nfs_file_localio {
> > + struct nfsd_file __rcu *ro_file;
> > + struct nfsd_file __rcu *rw_file;
> > + struct list_head list;
> > + void __rcu *nfs_uuid; /* opaque pointer to 'nfs_uuid_t' */
>
> I've said it above but just to be clear: No "__rcu" here.
Please look at final form of nfs_close_local_fh() with all patches
applied. I wanted to avoid churn in nfs_close_local_fh(), but yeah it
does have some needless RCU-ification in this intermediate patch.
That said, could be there is still room for cleanup even with the
final nfs_close_local_fh()...
Thanks,
Mike
next prev parent reply other threads:[~2024-11-15 16:49 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-14 3:59 [for-6.13 PATCH v2 00/15] nfs/nfsd: fixes and improvements for LOCALIO Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 01/15] nfs_common: must not hold RCU while calling nfsd_file_put_local Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 02/15] nfs/localio: add direct IO enablement with sync and async IO support Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 03/15] nfsd: add nfsd_file_{get,put} to 'nfs_to' nfsd_localio_operations Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 04/15] nfs_common: rename functions that invalidate LOCALIO nfs_clients Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 05/15] nfs_common: move localio_lock to new lock member of nfs_uuid_t Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 06/15] nfs: cache all open LOCALIO nfsd_file(s) in client Mike Snitzer
2024-11-15 3:12 ` NeilBrown
2024-11-15 16:49 ` Mike Snitzer [this message]
2024-11-14 3:59 ` [for-6.13 PATCH v2 07/15] nfsd: update percpu_ref to manage references on nfsd_net Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 08/15] nfsd: rename nfsd_serv_ prefixed methods and variables with nfsd_net_ Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 09/15] nfsd: nfsd_file_acquire_local no longer returns GC'd nfsd_file Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 10/15] nfs_common: rename nfslocalio nfs_uuid_lock to nfs_uuids_lock Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 11/15] nfs_common: track all open nfsd_files per LOCALIO nfs_client Mike Snitzer
2024-11-14 18:53 ` Jeff Layton
2024-11-14 23:22 ` Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 12/15] nfs_common: add nfs_localio trace events Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 13/15] nfs/localio: remove redundant code and simplify LOCALIO enablement Mike Snitzer
2024-11-14 15:31 ` [for-6.13 PATCH v2-fixed " Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 14/15] nfs: probe for LOCALIO when v4 client reconnects to server Mike Snitzer
2024-11-14 3:59 ` [for-6.13 PATCH v2 15/15] nfs: probe for LOCALIO when v3 " Mike Snitzer
2024-11-15 3:55 ` NeilBrown
2024-11-14 16:14 ` (subset) [for-6.13 PATCH v2 00/15] nfs/nfsd: fixes and improvements for LOCALIO cel
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=Zzd7hKl5_cu4yP2s@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=neilb@suse.de \
--cc=trondmy@hammerspace.com \
/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