From: Jeff Layton <jlayton@kernel.org>
To: Benjamin Coddington <bcodding@redhat.com>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH 2/2] NFSv4: Allow FREE_STATEID to clean up delegations
Date: Wed, 23 Apr 2025 15:41:13 -0400 [thread overview]
Message-ID: <f768ca3c27d1b0e6934a7ec319fa2ea9d0778b07.camel@kernel.org> (raw)
In-Reply-To: <e8c113d33be1bf52016b6b747330eec5c17dc948.1745430006.git.bcodding@redhat.com>
On Wed, 2025-04-23 at 13:59 -0400, Benjamin Coddington wrote:
> The NFS client's list of delegations can grow quite large (well beyond the
> delegation watermark) if the server is revoking or there are repeated
> events that expire state. Once this happens, the revoked delegations can
> cause a performance problem for subsequent walks of the
> servers->delegations list when the client tries to test and free state.
>
> If we can determine that the FREE_STATEID operation has completed without
> error, we can prune the delegation from the list.
>
> Since the NFS client combines TEST_STATEID with FREE_STATEID in its minor
> version operations, there isn't an easy way to communicate success of
> FREE_STATEID. Rather than re-arrange quite a number of calling paths to
> break out the separate procedures, let's signal the success of FREE_STATEID
> by setting the stateid's type.
>
> Set NFS4_FREED_STATEID_TYPE for stateids that have been successfully
> discarded from the server, and use that type to signal that the delegation
> can be cleaned up.
>
> Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
> ---
> fs/nfs/delegation.c | 25 ++++++++++++++++++-------
> fs/nfs/nfs4_fs.h | 3 +--
> fs/nfs/nfs4proc.c | 11 +++++------
> include/linux/nfs4.h | 1 +
> 4 files changed, 25 insertions(+), 15 deletions(-)
>
> diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
> index 4db912f56230..b746793cf730 100644
> --- a/fs/nfs/delegation.c
> +++ b/fs/nfs/delegation.c
> @@ -1006,13 +1006,6 @@ static void nfs_revoke_delegation(struct inode *inode,
> nfs_inode_find_state_and_recover(inode, stateid);
> }
>
> -void nfs_remove_bad_delegation(struct inode *inode,
> - const nfs4_stateid *stateid)
> -{
> - nfs_revoke_delegation(inode, stateid);
> -}
> -EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
> -
> void nfs_delegation_mark_returned(struct inode *inode,
> const nfs4_stateid *stateid)
> {
> @@ -1054,6 +1047,24 @@ void nfs_delegation_mark_returned(struct inode *inode,
> nfs_inode_find_state_and_recover(inode, stateid);
> }
>
> +/**
> + * nfs_remove_bad_delegation - handle delegations that are unusable
> + * @inode: inode to process
> + * @stateid: the delegation's stateid
> + *
> + * If the server ACK-ed our FREE_STATEID then clean
> + * up the delegation, else mark and keep the revoked state.
> + */
> +void nfs_remove_bad_delegation(struct inode *inode,
> + const nfs4_stateid *stateid)
> +{
> + if (stateid && stateid->type == NFS4_FREED_STATEID_TYPE)
> + nfs_delegation_mark_returned(inode, stateid);
> + else
> + nfs_revoke_delegation(inode, stateid);
> +}
> +EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
> +
> /**
> * nfs_expire_unused_delegation_types
> * @clp: client to process
> diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
> index 7d383d29a995..d3ca91f60fc1 100644
> --- a/fs/nfs/nfs4_fs.h
> +++ b/fs/nfs/nfs4_fs.h
> @@ -67,8 +67,7 @@ struct nfs4_minor_version_ops {
> void (*free_lock_state)(struct nfs_server *,
> struct nfs4_lock_state *);
> int (*test_and_free_expired)(struct nfs_server *,
> - const nfs4_stateid *,
> - const struct cred *);
> + nfs4_stateid *, const struct cred *);
> struct nfs_seqid *
> (*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
> void (*session_trunk)(struct rpc_clnt *clnt,
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index bfb9e980d662..143cb191b0b8 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -105,7 +105,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
> bool is_privileged);
> static int nfs41_test_stateid(struct nfs_server *, const nfs4_stateid *,
> const struct cred *);
> -static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
> +static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *,
> const struct cred *, bool);
> #endif
>
> @@ -2886,16 +2886,14 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
> }
>
> static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
> - const nfs4_stateid *stateid,
> - const struct cred *cred)
> + nfs4_stateid *stateid, const struct cred *cred)
> {
> return -NFS4ERR_BAD_STATEID;
> }
>
> #if defined(CONFIG_NFS_V4_1)
> static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
> - const nfs4_stateid *stateid,
> - const struct cred *cred)
> + nfs4_stateid *stateid, const struct cred *cred)
> {
> int status;
>
> @@ -10572,7 +10570,7 @@ static const struct rpc_call_ops nfs41_free_stateid_ops = {
> * Note: this function is always asynchronous.
> */
> static int nfs41_free_stateid(struct nfs_server *server,
> - const nfs4_stateid *stateid,
> + nfs4_stateid *stateid,
> const struct cred *cred,
> bool privileged)
> {
> @@ -10612,6 +10610,7 @@ static int nfs41_free_stateid(struct nfs_server *server,
> if (IS_ERR(task))
> return PTR_ERR(task);
> rpc_put_task(task);
> + stateid->type = NFS4_FREED_STATEID_TYPE;
Would it be possible to call nfs_delegation_mark_returned() at this
point, and skip all of the type changing?
> return 0;
> }
>
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index 9ac83ca88326..8ec5766cb22f 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -72,6 +72,7 @@ struct nfs4_stateid_struct {
> NFS4_LAYOUT_STATEID_TYPE,
> NFS4_PNFS_DS_STATEID_TYPE,
> NFS4_REVOKED_STATEID_TYPE,
> + NFS4_FREED_STATEID_TYPE,
> } type;
> };
>
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2025-04-23 19:41 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-23 17:59 [PATCH 0/2] Allow FREE_STATEID to free delegations Benjamin Coddington
2025-04-23 17:59 ` [PATCH 1/2] NFSv4: Ensure test_and_free_stateid callers use private memory Benjamin Coddington
2025-04-23 20:35 ` Jeff Layton
2025-04-23 22:04 ` Benjamin Coddington
2025-04-29 14:01 ` Benjamin Coddington
2025-04-23 17:59 ` [PATCH 2/2] NFSv4: Allow FREE_STATEID to clean up delegations Benjamin Coddington
2025-04-23 19:41 ` Jeff Layton [this message]
2025-04-23 19:59 ` Benjamin Coddington
2025-04-23 20:37 ` Jeff Layton
2025-04-23 22:12 ` Benjamin Coddington
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=f768ca3c27d1b0e6934a7ec319fa2ea9d0778b07.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=anna@kernel.org \
--cc=bcodding@redhat.com \
--cc=linux-nfs@vger.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