]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
NFSv4: Avoid unnecessary scans of filesystems for expired delegations
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 19 Feb 2025 00:03:21 +0000 (19:03 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Apr 2025 12:39:24 +0000 (14:39 +0200)
[ Upstream commit f163aa81a799e2d46d7f8f0b42a0e7770eaa0d06 ]

The amount of looping through the list of delegations is occasionally
leading to soft lockups.  If the state manager was asked to reap the
expired delegations, it should scan only those filesystems that hold
delegations that need to be reaped.

Fixes: 7f156ef0bf45 ("NFSv4: Clean up nfs_delegation_reap_expired()")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/delegation.c
include/linux/nfs_fs_sb.h

index d1f5e497729c3b5fbdb6b4dbfa601017c9d7bf35..abd952cc47e4be7806e2ee6cb76731ec70b0f084 100644 (file)
@@ -1284,6 +1284,7 @@ static void nfs_mark_test_expired_delegation(struct nfs_server *server,
                return;
        clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
        set_bit(NFS_DELEGATION_TEST_EXPIRED, &delegation->flags);
+       set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags);
        set_bit(NFS4CLNT_DELEGATION_EXPIRED, &server->nfs_client->cl_state);
 }
 
@@ -1362,6 +1363,9 @@ static int nfs_server_reap_expired_delegations(struct nfs_server *server,
        nfs4_stateid stateid;
        unsigned long gen = ++server->delegation_gen;
 
+       if (!test_and_clear_bit(NFS4SERV_DELEGATION_EXPIRED,
+                               &server->delegation_flags))
+               return 0;
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
@@ -1391,6 +1395,9 @@ restart:
                        goto restart;
                }
                nfs_inode_mark_test_expired_delegation(server,inode);
+               set_bit(NFS4SERV_DELEGATION_EXPIRED, &server->delegation_flags);
+               set_bit(NFS4CLNT_DELEGATION_EXPIRED,
+                       &server->nfs_client->cl_state);
                iput(inode);
                return -EAGAIN;
        }
index 98fc10ee0b86943c535c63fc9178de9f0849e1e4..f4cb1f4850a0cb111d11e218b56550a7fcdf1a32 100644 (file)
@@ -253,6 +253,7 @@ struct nfs_server {
 
        unsigned long           delegation_flags;
 #define NFS4SERV_DELEGRETURN           (1)
+#define NFS4SERV_DELEGATION_EXPIRED    (2)
        unsigned long           delegation_gen;
        unsigned long           mig_gen;
        unsigned long           mig_status;