|
@@ -4693,6 +4693,28 @@ nfsd4_end_grace(struct nfsd_net *nn)
|
|
|
*/
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * If we've waited a lease period but there are still clients trying to
|
|
|
+ * reclaim, wait a little longer to give them a chance to finish.
|
|
|
+ */
|
|
|
+static bool clients_still_reclaiming(struct nfsd_net *nn)
|
|
|
+{
|
|
|
+ unsigned long now = get_seconds();
|
|
|
+ unsigned long double_grace_period_end = nn->boot_time +
|
|
|
+ 2 * nn->nfsd4_lease;
|
|
|
+
|
|
|
+ if (!nn->somebody_reclaimed)
|
|
|
+ return false;
|
|
|
+ nn->somebody_reclaimed = false;
|
|
|
+ /*
|
|
|
+ * If we've given them *two* lease times to reclaim, and they're
|
|
|
+ * still not done, give up:
|
|
|
+ */
|
|
|
+ if (time_after(now, double_grace_period_end))
|
|
|
+ return false;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static time_t
|
|
|
nfs4_laundromat(struct nfsd_net *nn)
|
|
|
{
|
|
@@ -4706,6 +4728,11 @@ nfs4_laundromat(struct nfsd_net *nn)
|
|
|
time_t t, new_timeo = nn->nfsd4_lease;
|
|
|
|
|
|
dprintk("NFSD: laundromat service - starting\n");
|
|
|
+
|
|
|
+ if (clients_still_reclaiming(nn)) {
|
|
|
+ new_timeo = 0;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
nfsd4_end_grace(nn);
|
|
|
INIT_LIST_HEAD(&reaplist);
|
|
|
spin_lock(&nn->client_lock);
|
|
@@ -4803,7 +4830,7 @@ nfs4_laundromat(struct nfsd_net *nn)
|
|
|
posix_unblock_lock(&nbl->nbl_lock);
|
|
|
free_blocked_lock(nbl);
|
|
|
}
|
|
|
-
|
|
|
+out:
|
|
|
new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
|
|
|
return new_timeo;
|
|
|
}
|
|
@@ -6053,6 +6080,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
|
case 0: /* success! */
|
|
|
nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
|
|
|
status = 0;
|
|
|
+ if (lock->lk_reclaim)
|
|
|
+ nn->somebody_reclaimed = true;
|
|
|
break;
|
|
|
case FILE_LOCK_DEFERRED:
|
|
|
nbl = NULL;
|