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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.