Skip to content

Commit 956fd46

Browse files
Trond Myklebustamschuma-ntap
authored andcommitted
NFSv4: Fix a state manager thread deadlock regression
Commit 4dc73c6 reintroduces the deadlock that was fixed by commit aeabb3c ("NFSv4: Fix a NFSv4 state manager deadlock") because it prevents the setup of new threads to handle reboot recovery, while the older recovery thread is stuck returning delegations. Fixes: 4dc73c6 ("NFSv4: keep state manager thread active if swap is enabled") Cc: [email protected] Signed-off-by: Trond Myklebust <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent ed1cc05 commit 956fd46

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

fs/nfs/nfs4proc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10622,7 +10622,9 @@ static void nfs4_disable_swap(struct inode *inode)
1062210622
*/
1062310623
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
1062410624

10625-
nfs4_schedule_state_manager(clp);
10625+
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
10626+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
10627+
wake_up_var(&clp->cl_state);
1062610628
}
1062710629

1062810630
static const struct inode_operations nfs4_dir_inode_operations = {

fs/nfs/nfs4state.c

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,16 +1209,26 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
12091209
{
12101210
struct task_struct *task;
12111211
char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];
1212+
struct rpc_clnt *clnt = clp->cl_rpcclient;
1213+
bool swapon = false;
12121214

1213-
if (clp->cl_rpcclient->cl_shutdown)
1215+
if (clnt->cl_shutdown)
12141216
return;
12151217

12161218
set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
1217-
if (test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) != 0) {
1218-
wake_up_var(&clp->cl_state);
1219-
return;
1219+
1220+
if (atomic_read(&clnt->cl_swapper)) {
1221+
swapon = !test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE,
1222+
&clp->cl_state);
1223+
if (!swapon) {
1224+
wake_up_var(&clp->cl_state);
1225+
return;
1226+
}
12201227
}
1221-
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
1228+
1229+
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
1230+
return;
1231+
12221232
__module_get(THIS_MODULE);
12231233
refcount_inc(&clp->cl_count);
12241234

@@ -1235,8 +1245,9 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
12351245
__func__, PTR_ERR(task));
12361246
if (!nfs_client_init_is_complete(clp))
12371247
nfs_mark_client_ready(clp, PTR_ERR(task));
1248+
if (swapon)
1249+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
12381250
nfs4_clear_state_manager_bit(clp);
1239-
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
12401251
nfs_put_client(clp);
12411252
module_put(THIS_MODULE);
12421253
}
@@ -2748,22 +2759,25 @@ static int nfs4_run_state_manager(void *ptr)
27482759

27492760
allow_signal(SIGKILL);
27502761
again:
2751-
set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state);
27522762
nfs4_state_manager(clp);
2753-
if (atomic_read(&cl->cl_swapper)) {
2763+
2764+
if (test_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state) &&
2765+
!test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state)) {
27542766
wait_var_event_interruptible(&clp->cl_state,
27552767
test_bit(NFS4CLNT_RUN_MANAGER,
27562768
&clp->cl_state));
2757-
if (atomic_read(&cl->cl_swapper) &&
2758-
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
2769+
if (!atomic_read(&cl->cl_swapper))
2770+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
2771+
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
2772+
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
27592773
goto again;
27602774
/* Either no longer a swapper, or were signalled */
2775+
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
27612776
}
2762-
clear_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state);
27632777

27642778
if (refcount_read(&clp->cl_count) > 1 && !signalled() &&
27652779
test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) &&
2766-
!test_and_set_bit(NFS4CLNT_MANAGER_AVAILABLE, &clp->cl_state))
2780+
!test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state))
27672781
goto again;
27682782

27692783
nfs_put_client(clp);

0 commit comments

Comments
 (0)