Currently the error returned from nfs4_reclaim_lease to the state manager is not recorded in cl_cons_state via nfs_mark_client_ready in the nfsv4.0 case. We can store it in cl_lease_time since it is useless until the lease is reclaimed. The status can then be fetched in nfs4_recover_expired_lease if cl_state is still marked with NFS4CLNT_LEASE_EXPIRED. This can be reproduced by having an /etc/exports entry on the server that exports a non-existing path. Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> Cc: Andy Adamson <andros@xxxxxxxxxx> --- fs/nfs/client.c | 1 + fs/nfs/nfs4proc.c | 16 ++++++++++++---- fs/nfs/nfs4state.c | 2 ++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/nfs/client.c b/fs/nfs/client.c index c2d0616..157a1d9 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -149,6 +149,7 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_ clp->cl_boot_time = CURRENT_TIME; clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; clp->cl_minorversion = cl_init->minorversion; + clp->cl_lease_time = 0; #endif cred = rpc_lookup_machine_cred(); if (!IS_ERR(cred)) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 92ce435..596442b 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1450,13 +1450,21 @@ static int nfs4_recover_expired_lease(struct nfs_server *server) for (;;) { ret = nfs4_wait_clnt_recover(clp); if (ret != 0) - return ret; - if (!test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && - !test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state)) break; + /* Is lease recovery done? */ + if (!test_bit(NFS4CLNT_CHECK_LEASE,&clp->cl_state) && + !test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) + break; + if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) && + clp->cl_lease_time) { + /* fetch the lease reclaim error */ + ret = (int)clp->cl_lease_time; + break; + } nfs4_schedule_state_recovery(clp); } - return 0; + dprintk("%s: error=%d\n", __func__, ret); + return ret; } /* diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index b73c5a7..cabe5fc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1220,6 +1220,7 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status) return; } } + clp->cl_lease_time = status; set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); } @@ -1231,6 +1232,7 @@ static void nfs4_state_manager(struct nfs_client *clp) for(;;) { if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) { /* We're going to have to re-establish a clientid */ + clp->cl_lease_time = 0; status = nfs4_reclaim_lease(clp); if (status) { nfs4_set_lease_expired(clp, status); -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html