Skip to content

Commit 6f9449b

Browse files
author
Trond Myklebust
committed
NFS: Fix a soft lockup in the delegation recovery code
Fix a soft lockup when NFS client delegation recovery is attempted but the inode is in the process of being freed. When the igrab(inode) call fails, and we have to restart the recovery process, we need to ensure that we won't attempt to recover the same delegation again. Fixes: 45870d6 ("NFSv4.1: Test delegation stateids when server...") Signed-off-by: Trond Myklebust <[email protected]>
1 parent 3453d57 commit 6f9449b

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

fs/nfs/delegation.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation
229229
spin_lock(&delegation->lock);
230230
if (delegation->inode != NULL)
231231
inode = igrab(delegation->inode);
232+
if (!inode)
233+
set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
232234
spin_unlock(&delegation->lock);
233235
return inode;
234236
}
@@ -944,10 +946,11 @@ void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
944946
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
945947
list_for_each_entry_rcu(delegation, &server->delegations,
946948
super_list) {
947-
if (test_bit(NFS_DELEGATION_RETURNING,
948-
&delegation->flags))
949-
continue;
950-
if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
949+
if (test_bit(NFS_DELEGATION_INODE_FREEING,
950+
&delegation->flags) ||
951+
test_bit(NFS_DELEGATION_RETURNING,
952+
&delegation->flags) ||
953+
test_bit(NFS_DELEGATION_NEED_RECLAIM,
951954
&delegation->flags) == 0)
952955
continue;
953956
if (!nfs_sb_active(server->super))
@@ -1053,10 +1056,11 @@ void nfs_reap_expired_delegations(struct nfs_client *clp)
10531056
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
10541057
list_for_each_entry_rcu(delegation, &server->delegations,
10551058
super_list) {
1056-
if (test_bit(NFS_DELEGATION_RETURNING,
1057-
&delegation->flags))
1058-
continue;
1059-
if (test_bit(NFS_DELEGATION_TEST_EXPIRED,
1059+
if (test_bit(NFS_DELEGATION_INODE_FREEING,
1060+
&delegation->flags) ||
1061+
test_bit(NFS_DELEGATION_RETURNING,
1062+
&delegation->flags) ||
1063+
test_bit(NFS_DELEGATION_TEST_EXPIRED,
10601064
&delegation->flags) == 0)
10611065
continue;
10621066
if (!nfs_sb_active(server->super))

fs/nfs/delegation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ enum {
3434
NFS_DELEGATION_RETURNING,
3535
NFS_DELEGATION_REVOKED,
3636
NFS_DELEGATION_TEST_EXPIRED,
37+
NFS_DELEGATION_INODE_FREEING,
3738
};
3839

3940
int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred,

0 commit comments

Comments
 (0)