Skip to content

Commit 7cede02

Browse files
committed
Merge: NFSv4: Allow FREE_STATEID to clean up delegations
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7145 JIRA: https://issues.redhat.com/browse/RHEL-70625 commit 77be29b Author: Benjamin Coddington <bcodding@redhat.com> Date: Thu May 1 08:29:42 2025 -0400 NFSv4: Allow FREE_STATEID to clean up delegations 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> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> Signed-off-by: Benjamin Coddington <bcodding@redhat.com> Approved-by: Olga Kornievskaia <okorniev@redhat.com> Approved-by: Scott Mayhew <smayhew@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents c3cc9c0 + ac5ba1f commit 7cede02

File tree

4 files changed

+26
-15
lines changed

4 files changed

+26
-15
lines changed

fs/nfs/delegation.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -969,13 +969,6 @@ static void nfs_revoke_delegation(struct inode *inode,
969969
nfs_inode_find_state_and_recover(inode, stateid);
970970
}
971971

972-
void nfs_remove_bad_delegation(struct inode *inode,
973-
const nfs4_stateid *stateid)
974-
{
975-
nfs_revoke_delegation(inode, stateid);
976-
}
977-
EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
978-
979972
void nfs_delegation_mark_returned(struct inode *inode,
980973
const nfs4_stateid *stateid)
981974
{
@@ -1012,6 +1005,24 @@ void nfs_delegation_mark_returned(struct inode *inode,
10121005
nfs_inode_find_state_and_recover(inode, stateid);
10131006
}
10141007

1008+
/**
1009+
* nfs_remove_bad_delegation - handle delegations that are unusable
1010+
* @inode: inode to process
1011+
* @stateid: the delegation's stateid
1012+
*
1013+
* If the server ACK-ed our FREE_STATEID then clean
1014+
* up the delegation, else mark and keep the revoked state.
1015+
*/
1016+
void nfs_remove_bad_delegation(struct inode *inode,
1017+
const nfs4_stateid *stateid)
1018+
{
1019+
if (stateid && stateid->type == NFS4_FREED_STATEID_TYPE)
1020+
nfs_delegation_mark_returned(inode, stateid);
1021+
else
1022+
nfs_revoke_delegation(inode, stateid);
1023+
}
1024+
EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
1025+
10151026
/**
10161027
* nfs_expire_unused_delegation_types
10171028
* @clp: client to process

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ struct nfs4_minor_version_ops {
6767
void (*free_lock_state)(struct nfs_server *,
6868
struct nfs4_lock_state *);
6969
int (*test_and_free_expired)(struct nfs_server *,
70-
const nfs4_stateid *,
71-
const struct cred *);
70+
nfs4_stateid *, const struct cred *);
7271
struct nfs_seqid *
7372
(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t);
7473
void (*session_trunk)(struct rpc_clnt *clnt,

fs/nfs/nfs4proc.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
105105
bool is_privileged);
106106
static int nfs41_test_stateid(struct nfs_server *, const nfs4_stateid *,
107107
const struct cred *);
108-
static int nfs41_free_stateid(struct nfs_server *, const nfs4_stateid *,
108+
static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *,
109109
const struct cred *, bool);
110110
#endif
111111

@@ -2877,16 +2877,14 @@ static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *st
28772877
}
28782878

28792879
static int nfs40_test_and_free_expired_stateid(struct nfs_server *server,
2880-
const nfs4_stateid *stateid,
2881-
const struct cred *cred)
2880+
nfs4_stateid *stateid, const struct cred *cred)
28822881
{
28832882
return -NFS4ERR_BAD_STATEID;
28842883
}
28852884

28862885
#if defined(CONFIG_NFS_V4_1)
28872886
static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
2888-
const nfs4_stateid *stateid,
2889-
const struct cred *cred)
2887+
nfs4_stateid *stateid, const struct cred *cred)
28902888
{
28912889
int status;
28922890

@@ -2895,6 +2893,7 @@ static int nfs41_test_and_free_expired_stateid(struct nfs_server *server,
28952893
break;
28962894
case NFS4_INVALID_STATEID_TYPE:
28972895
case NFS4_SPECIAL_STATEID_TYPE:
2896+
case NFS4_FREED_STATEID_TYPE:
28982897
return -NFS4ERR_BAD_STATEID;
28992898
case NFS4_REVOKED_STATEID_TYPE:
29002899
goto out_free;
@@ -10556,7 +10555,7 @@ static const struct rpc_call_ops nfs41_free_stateid_ops = {
1055610555
* Note: this function is always asynchronous.
1055710556
*/
1055810557
static int nfs41_free_stateid(struct nfs_server *server,
10559-
const nfs4_stateid *stateid,
10558+
nfs4_stateid *stateid,
1056010559
const struct cred *cred,
1056110560
bool privileged)
1056210561
{
@@ -10596,6 +10595,7 @@ static int nfs41_free_stateid(struct nfs_server *server,
1059610595
if (IS_ERR(task))
1059710596
return PTR_ERR(task);
1059810597
rpc_put_task(task);
10598+
stateid->type = NFS4_FREED_STATEID_TYPE;
1059910599
return 0;
1060010600
}
1060110601

include/linux/nfs4.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct nfs4_stateid_struct {
7070
NFS4_LAYOUT_STATEID_TYPE,
7171
NFS4_PNFS_DS_STATEID_TYPE,
7272
NFS4_REVOKED_STATEID_TYPE,
73+
NFS4_FREED_STATEID_TYPE,
7374
} type;
7475
};
7576

0 commit comments

Comments
 (0)