SUNRPC: Fix potential races in xprt_lock_write_next()

We have to ensure that the wake up from the waitqueue and the assignment
of xprt->snd_task are atomic. We can do this by assigning the snd_task
while under the waitqueue spinlock.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust
2012-01-17 22:57:37 -05:00
parent 2aeb98f498
commit 961a828df6
6 changed files with 79 additions and 46 deletions

View File

@@ -190,23 +190,22 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
static void nfs4_end_drain_session(struct nfs_client *clp)
{
struct nfs4_session *ses = clp->cl_session;
struct nfs4_slot_table *tbl;
int max_slots;
if (ses == NULL)
return;
tbl = &ses->fc_slot_table;
if (test_and_clear_bit(NFS4_SESSION_DRAINING, &ses->session_state)) {
spin_lock(&ses->fc_slot_table.slot_tbl_lock);
max_slots = ses->fc_slot_table.max_slots;
spin_lock(&tbl->slot_tbl_lock);
max_slots = tbl->max_slots;
while (max_slots--) {
struct rpc_task *task;
task = rpc_wake_up_next(&ses->fc_slot_table.
slot_tbl_waitq);
if (!task)
if (rpc_wake_up_first(&tbl->slot_tbl_waitq,
nfs4_set_task_privileged,
NULL) == NULL)
break;
rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED);
}
spin_unlock(&ses->fc_slot_table.slot_tbl_lock);
spin_unlock(&tbl->slot_tbl_lock);
}
}