summaryrefslogtreecommitdiff
path: root/fs/nfsd
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2024-01-30 04:08:31 +0300
committerChuck Lever <chuck.lever@oracle.com>2024-03-01 17:12:21 +0300
commit39657c740644e1468cfd2129f43d0ae08bd53531 (patch)
treeed7cd50e0711e4ea79243699a2801b9c42a5d304 /fs/nfsd
parent1c13bf9f2e3cd5a59ef988c6c5a49fe0f02bcdfc (diff)
downloadlinux-39657c740644e1468cfd2129f43d0ae08bd53531.tar.xz
nfsd: allow open state ids to be revoked and then freed
Revoking state through 'unlock_filesystem' now revokes any open states found. When the stateids are then freed by the client, the revoked stateids will be cleaned up correctly. Possibly the related lock states should be revoked too, but a subsequent patch will do that for all lock state on the superblock. Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4state.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 108ed0c0ecdb..bf105aa0218a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1717,7 +1717,7 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
unsigned int idhashval;
unsigned int sc_types;
- sc_types = SC_TYPE_LOCK;
+ sc_types = SC_TYPE_OPEN | SC_TYPE_LOCK;
spin_lock(&nn->client_lock);
for (idhashval = 0; idhashval < CLIENT_HASH_MASK; idhashval++) {
@@ -1732,6 +1732,22 @@ void nfsd4_revoke_states(struct net *net, struct super_block *sb)
spin_unlock(&nn->client_lock);
switch (stid->sc_type) {
+ case SC_TYPE_OPEN:
+ stp = openlockstateid(stid);
+ mutex_lock_nested(&stp->st_mutex,
+ OPEN_STATEID_MUTEX);
+
+ spin_lock(&clp->cl_lock);
+ if (stid->sc_status == 0) {
+ stid->sc_status |=
+ SC_STATUS_ADMIN_REVOKED;
+ atomic_inc(&clp->cl_admin_revoked);
+ spin_unlock(&clp->cl_lock);
+ release_all_access(stp);
+ } else
+ spin_unlock(&clp->cl_lock);
+ mutex_unlock(&stp->st_mutex);
+ break;
case SC_TYPE_LOCK:
stp = openlockstateid(stid);
mutex_lock_nested(&stp->st_mutex,
@@ -4663,6 +4679,13 @@ static void nfsd4_drop_revoked_stid(struct nfs4_stid *s)
bool unhashed;
switch (s->sc_type) {
+ case SC_TYPE_OPEN:
+ stp = openlockstateid(s);
+ if (unhash_open_stateid(stp, &reaplist))
+ put_ol_stateid_locked(stp, &reaplist);
+ spin_unlock(&cl->cl_lock);
+ free_ol_stateid_reaplist(&reaplist);
+ break;
case SC_TYPE_LOCK:
stp = openlockstateid(s);
unhashed = unhash_lock_stateid(stp);