Commit 5c31e236 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Fix nfs_server_return_all_delegations

If the state manager thread is already running, we may end up
racing with it in nfs_client_return_marked_delegations. Better to
just allow the state manager thread to do the job.
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent b757144f
...@@ -502,6 +502,18 @@ static void nfs_mark_return_delegation(struct nfs_server *server, ...@@ -502,6 +502,18 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
} }
static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
{
struct nfs_delegation *delegation;
bool ret = false;
list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
nfs_mark_return_delegation(server, delegation);
ret = true;
}
return ret;
}
/** /**
* nfs_super_return_all_delegations - return delegations for one superblock * nfs_super_return_all_delegations - return delegations for one superblock
* @sb: sb to process * @sb: sb to process
...@@ -510,21 +522,19 @@ static void nfs_mark_return_delegation(struct nfs_server *server, ...@@ -510,21 +522,19 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
void nfs_server_return_all_delegations(struct nfs_server *server) void nfs_server_return_all_delegations(struct nfs_server *server)
{ {
struct nfs_client *clp = server->nfs_client; struct nfs_client *clp = server->nfs_client;
struct nfs_delegation *delegation; bool need_wait;
if (clp == NULL) if (clp == NULL)
return; return;
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(delegation, &server->delegations, super_list) { need_wait = nfs_server_mark_return_all_delegations(server);
spin_lock(&delegation->lock);
set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
spin_unlock(&delegation->lock);
}
rcu_read_unlock(); rcu_read_unlock();
if (nfs_client_return_marked_delegations(clp) != 0) if (need_wait) {
nfs4_schedule_state_manager(clp); nfs4_schedule_state_manager(clp);
nfs4_wait_clnt_recover(clp);
}
} }
static void nfs_mark_return_all_delegation_types(struct nfs_server *server, static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment