]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nfsd: allow open state ids to be revoked and then freed
authorNeilBrown <neilb@suse.de>
Tue, 30 Jan 2024 01:08:31 +0000 (12:08 +1100)
committerChuck Lever <chuck.lever@oracle.com>
Fri, 1 Mar 2024 14:12:21 +0000 (09:12 -0500)
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>
fs/nfsd/nfs4state.c

index 108ed0c0ecdb4174b3d92629418bdaacb3a7eb4d..bf105aa0218a85dd9030a035b01c155e254a5612 100644 (file)
@@ -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);