Commit 03f318ca authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd4: extend reclaim period for reclaiming clients

If the client is only renewing state a little sooner than once a lease
period, then it might not discover the server has restarted till close
to the end of the grace period, and might run out of time to do the
actual reclaim.

Extend the grace period by a second each time we notice there are
clients still trying to reclaim, up to a limit of another whole lease
period.
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent ce397d21
...@@ -102,6 +102,7 @@ struct nfsd_net { ...@@ -102,6 +102,7 @@ struct nfsd_net {
time_t nfsd4_lease; time_t nfsd4_lease;
time_t nfsd4_grace; time_t nfsd4_grace;
bool somebody_reclaimed;
bool nfsd_net_up; bool nfsd_net_up;
bool lockd_up; bool lockd_up;
......
...@@ -354,6 +354,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -354,6 +354,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct svc_fh *resfh = NULL; struct svc_fh *resfh = NULL;
struct net *net = SVC_NET(rqstp); struct net *net = SVC_NET(rqstp);
struct nfsd_net *nn = net_generic(net, nfsd_net_id); struct nfsd_net *nn = net_generic(net, nfsd_net_id);
bool reclaim = false;
dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n", dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
(int)open->op_fname.len, open->op_fname.data, (int)open->op_fname.len, open->op_fname.data,
...@@ -424,6 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -424,6 +425,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (status) if (status)
goto out; goto out;
open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
reclaim = true;
case NFS4_OPEN_CLAIM_FH: case NFS4_OPEN_CLAIM_FH:
case NFS4_OPEN_CLAIM_DELEG_CUR_FH: case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
status = do_open_fhandle(rqstp, cstate, open); status = do_open_fhandle(rqstp, cstate, open);
...@@ -452,6 +454,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -452,6 +454,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
WARN(status && open->op_created, WARN(status && open->op_created,
"nfsd4_process_open2 failed to open newly-created file! status=%u\n", "nfsd4_process_open2 failed to open newly-created file! status=%u\n",
be32_to_cpu(status)); be32_to_cpu(status));
if (reclaim && !status)
nn->somebody_reclaimed = true;
out: out:
if (resfh && resfh != &cstate->current_fh) { if (resfh && resfh != &cstate->current_fh) {
fh_dup2(&cstate->current_fh, resfh); fh_dup2(&cstate->current_fh, resfh);
......
...@@ -4693,6 +4693,28 @@ nfsd4_end_grace(struct nfsd_net *nn) ...@@ -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 static time_t
nfs4_laundromat(struct nfsd_net *nn) nfs4_laundromat(struct nfsd_net *nn)
{ {
...@@ -4706,6 +4728,11 @@ nfs4_laundromat(struct nfsd_net *nn) ...@@ -4706,6 +4728,11 @@ nfs4_laundromat(struct nfsd_net *nn)
time_t t, new_timeo = nn->nfsd4_lease; time_t t, new_timeo = nn->nfsd4_lease;
dprintk("NFSD: laundromat service - starting\n"); dprintk("NFSD: laundromat service - starting\n");
if (clients_still_reclaiming(nn)) {
new_timeo = 0;
goto out;
}
nfsd4_end_grace(nn); nfsd4_end_grace(nn);
INIT_LIST_HEAD(&reaplist); INIT_LIST_HEAD(&reaplist);
spin_lock(&nn->client_lock); spin_lock(&nn->client_lock);
...@@ -4803,7 +4830,7 @@ nfs4_laundromat(struct nfsd_net *nn) ...@@ -4803,7 +4830,7 @@ nfs4_laundromat(struct nfsd_net *nn)
posix_unblock_lock(&nbl->nbl_lock); posix_unblock_lock(&nbl->nbl_lock);
free_blocked_lock(nbl); free_blocked_lock(nbl);
} }
out:
new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT); new_timeo = max_t(time_t, new_timeo, NFSD_LAUNDROMAT_MINTIMEOUT);
return new_timeo; return new_timeo;
} }
...@@ -6053,6 +6080,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -6053,6 +6080,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
case 0: /* success! */ case 0: /* success! */
nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid); nfs4_inc_and_copy_stateid(&lock->lk_resp_stateid, &lock_stp->st_stid);
status = 0; status = 0;
if (lock->lk_reclaim)
nn->somebody_reclaimed = true;
break; break;
case FILE_LOCK_DEFERRED: case FILE_LOCK_DEFERRED:
nbl = NULL; nbl = NULL;
......
...@@ -1239,6 +1239,7 @@ static __net_init int nfsd_init_net(struct net *net) ...@@ -1239,6 +1239,7 @@ static __net_init int nfsd_init_net(struct net *net)
goto out_idmap_error; goto out_idmap_error;
nn->nfsd4_lease = 90; /* default lease time */ nn->nfsd4_lease = 90; /* default lease time */
nn->nfsd4_grace = 90; nn->nfsd4_grace = 90;
nn->somebody_reclaimed = false;
nn->clverifier_counter = prandom_u32(); nn->clverifier_counter = prandom_u32();
nn->clientid_counter = prandom_u32(); nn->clientid_counter = prandom_u32();
......
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