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

Lockd: Fix waiting on the server grace period.

  The old code was wrong in that it assumed that we are out the grace
  period as soon as the client is finished doing lock recovery.
  Also ensure that we respect signals when waiting for the server grace
  period to end.
parent 0a496096
...@@ -228,7 +228,6 @@ reclaimer(void *ptr) ...@@ -228,7 +228,6 @@ reclaimer(void *ptr)
} }
host->h_reclaiming = 0; host->h_reclaiming = 0;
wake_up(&host->h_gracewait);
/* Now, wake up all processes that sleep on a blocked lock */ /* Now, wake up all processes that sleep on a blocked lock */
for (block = nlm_blocked; block; block = block->b_next) { for (block = nlm_blocked; block; block = block->b_next) {
......
...@@ -217,6 +217,21 @@ nlmclnt_alloc_call(void) ...@@ -217,6 +217,21 @@ nlmclnt_alloc_call(void)
return NULL; return NULL;
} }
static int nlm_wait_on_grace(wait_queue_head_t *queue)
{
DEFINE_WAIT(wait);
int status = -EINTR;
prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
if (!signalled ()) {
schedule_timeout(NLMCLNT_GRACE_WAIT);
if (!signalled ())
status = 0;
}
finish_wait(queue, &wait);
return status;
}
/* /*
* Generic NLM call * Generic NLM call
*/ */
...@@ -241,10 +256,8 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) ...@@ -241,10 +256,8 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
msg.rpc_cred = nfs_file_cred(filp); msg.rpc_cred = nfs_file_cred(filp);
do { do {
if (host->h_reclaiming && !argp->reclaim) { if (host->h_reclaiming && !argp->reclaim)
interruptible_sleep_on(&host->h_gracewait); goto in_grace_period;
continue;
}
/* If we have no RPC client yet, create one. */ /* If we have no RPC client yet, create one. */
if ((clnt = nlm_bind_host(host)) == NULL) if ((clnt = nlm_bind_host(host)) == NULL)
...@@ -279,22 +292,23 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) ...@@ -279,22 +292,23 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc)
return -ENOLCK; return -ENOLCK;
} }
} else { } else {
if (!argp->reclaim) {
/* We appear to be out of the grace period */
wake_up_all(&host->h_gracewait);
}
dprintk("lockd: server returns status %d\n", resp->status); dprintk("lockd: server returns status %d\n", resp->status);
return 0; /* Okay, call complete */ return 0; /* Okay, call complete */
} }
/* Back off a little and try again */ in_grace_period:
interruptible_sleep_on_timeout(&host->h_gracewait, 15*HZ); /*
* The server has rebooted and appears to be in the grace
/* When the lock requested by F_SETLKW isn't available, * period during which locks are only allowed to be
we will wait until the request can be satisfied. If * reclaimed.
a signal is received during wait, we should return * We can only back off and try again later.
-EINTR. */ */
if (signalled ()) { status = nlm_wait_on_grace(&host->h_gracewait);
status = -EINTR; } while (status == 0);
break;
}
} while (1);
return status; return status;
} }
......
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