diff options
-rw-r--r-- | fs/nfs/nfs4state.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 7775435ea7a5..46eb624e4f16 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -71,6 +71,29 @@ static int nfs4_init_client(struct nfs_client *clp, struct rpc_cred *cred) return status; } +static struct rpc_cred *nfs4_get_machine_cred(struct nfs_client *clp) +{ + struct rpc_cred *cred = NULL; + + spin_lock(&clp->cl_lock); + if (clp->cl_machine_cred != NULL) + cred = get_rpccred(clp->cl_machine_cred); + spin_unlock(&clp->cl_lock); + return cred; +} + +static void nfs4_clear_machine_cred(struct nfs_client *clp) +{ + struct rpc_cred *cred; + + spin_lock(&clp->cl_lock); + cred = clp->cl_machine_cred; + clp->cl_machine_cred = NULL; + spin_unlock(&clp->cl_lock); + if (cred != NULL) + put_rpccred(cred); +} + struct rpc_cred *nfs4_get_renew_cred(struct nfs_client *clp) { struct nfs4_state_owner *sp; @@ -91,13 +114,18 @@ static struct rpc_cred *nfs4_get_setclientid_cred(struct nfs_client *clp) { struct nfs4_state_owner *sp; struct rb_node *pos; + struct rpc_cred *cred; + cred = nfs4_get_machine_cred(clp); + if (cred != NULL) + goto out; pos = rb_first(&clp->cl_state_owners); if (pos != NULL) { sp = rb_entry(pos, struct nfs4_state_owner, so_client_node); - return get_rpccred(sp->so_cred); + cred = get_rpccred(sp->so_cred); } - return NULL; +out: + return cred; } static void nfs_alloc_unique_id(struct rb_root *root, struct nfs_unique_id *new, @@ -924,10 +952,10 @@ restart_loop: if (cred != NULL) { /* Yes there are: try to renew the old lease */ status = nfs4_proc_renew(clp, cred); + put_rpccred(cred); switch (status) { case 0: case -NFS4ERR_CB_PATH_DOWN: - put_rpccred(cred); goto out; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_LEASE_MOVED: @@ -936,14 +964,19 @@ restart_loop: } else { /* "reboot" to ensure we clear all state on the server */ clp->cl_boot_time = CURRENT_TIME; - cred = nfs4_get_setclientid_cred(clp); } /* We're going to have to re-establish a clientid */ nfs4_state_mark_reclaim(clp); status = -ENOENT; + cred = nfs4_get_setclientid_cred(clp); if (cred != NULL) { status = nfs4_init_client(clp, cred); put_rpccred(cred); + /* Handle case where the user hasn't set up machine creds */ + if (status == -EACCES && cred == clp->cl_machine_cred) { + nfs4_clear_machine_cred(clp); + goto restart_loop; + } } if (status) goto out_error; |