Newer
Older
cred = nfs4_get_exchange_id_cred(clp);
status = nfs4_proc_destroy_session(clp->cl_session, cred);
if (status && status != -NFS4ERR_BADSESSION &&
status != -NFS4ERR_DEADSESSION) {

Ricardo Labiaga
committed
status = nfs4_recovery_handle_error(clp, status);
goto out;
}
memset(clp->cl_session->sess_id.data, 0, NFS4_MAX_SESSIONID_LEN);
status = nfs4_proc_create_session(clp, cred);
dprintk("%s: session reset failed with status %d for server %s!\n",
__func__, status, clp->cl_hostname);
status = nfs4_handle_reclaim_lease_error(clp, status);
nfs41_finish_session_reset(clp);
dprintk("%s: session reset was successful for server %s!\n",
__func__, clp->cl_hostname);
if (cred)
put_rpccred(cred);
static int nfs4_recall_slot(struct nfs_client *clp)
{
struct nfs4_slot *new, *old;
int i;
if (!nfs4_has_session(clp))
return 0;
fc_tbl = &clp->cl_session->fc_slot_table;
new = kmalloc(fc_tbl->target_max_slots * sizeof(struct nfs4_slot),
if (!new)
return -ENOMEM;
spin_lock(&fc_tbl->slot_tbl_lock);
for (i = 0; i < fc_tbl->target_max_slots; i++)
new[i].seq_nr = fc_tbl->slots[i].seq_nr;
old = fc_tbl->slots;
fc_tbl->slots = new;
fc_tbl->max_slots = fc_tbl->target_max_slots;
fc_tbl->target_max_slots = 0;
clp->cl_session->fc_attrs.max_reqs = fc_tbl->max_slots;
spin_unlock(&fc_tbl->slot_tbl_lock);
kfree(old);
return 0;
}
static int nfs4_bind_conn_to_session(struct nfs_client *clp)
{
struct rpc_cred *cred;
int ret;
if (!nfs4_has_session(clp))
return 0;
nfs4_begin_drain_session(clp);
cred = nfs4_get_exchange_id_cred(clp);
ret = nfs4_proc_bind_conn_to_session(clp, cred);
if (cred)
put_rpccred(cred);
clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
switch (ret) {
case 0:
dprintk("%s: bind_conn_to_session was successful for server %s!\n",
__func__, clp->cl_hostname);
break;
case -NFS4ERR_DELAY:
ssleep(1);
set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
break;
default:
return nfs4_recovery_handle_error(clp, ret);
}
return 0;
#else /* CONFIG_NFS_V4_1 */
static int nfs4_reset_session(struct nfs_client *clp) { return 0; }
static int nfs4_end_drain_session(struct nfs_client *clp) { return 0; }
static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
static int nfs4_bind_conn_to_session(struct nfs_client *clp)
{
return 0;
}
#endif /* CONFIG_NFS_V4_1 */
static void nfs4_state_manager(struct nfs_client *clp)
const char *section = "", *section_sep = "";
/* Ensure exclusive access to NFSv4 state */
if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
section = "purge state";
if (status < 0)
goto out_error;
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
section = "lease expired";
/* We're going to have to re-establish a clientid */
status = nfs4_reclaim_lease(clp);
if (status < 0)
goto out_error;
}
if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
section = "check lease";
status = nfs4_check_lease(clp);
if (status < 0)
goto out_error;
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
continue;
}
/* Initialize or reset the session */
if (test_and_clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state)) {
section = "reset session";
status = nfs4_reset_session(clp);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
continue;
if (status < 0)
/* Send BIND_CONN_TO_SESSION */
if (test_and_clear_bit(NFS4CLNT_BIND_CONN_TO_SESSION,
&clp->cl_state)) {
section = "bind conn to session";
status = nfs4_bind_conn_to_session(clp);
if (status < 0)
goto out_error;
/* Recall session slots */
if (test_and_clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state)) {
section = "recall slot";
status = nfs4_recall_slot(clp);
if (status < 0)
goto out_error;
continue;
}
/* First recover reboot state... */
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
section = "reclaim reboot";
clp->cl_mvops->reboot_recovery_ops);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state))
nfs4_state_end_reclaim_reboot(clp);
if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
continue;
if (status < 0)
goto out_error;
/* Now recover expired state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
section = "reclaim nograce";
clp->cl_mvops->nograce_recovery_ops);
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
test_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) ||
test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
continue;
if (status < 0)
goto out_error;
nfs4_end_drain_session(clp);
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
nfs_client_return_marked_delegations(clp);
continue;
}
nfs4_clear_state_manager_bit(clp);
/* Did we race with an attempt to give us more work? */
if (clp->cl_state == 0)
break;
if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
break;
} while (atomic_read(&clp->cl_count) > 1);
if (strlen(section))
section_sep = ": ";
pr_warn_ratelimited("NFS: state manager%s%s failed on NFSv4 server %s"
" with error %d\n", section_sep, section,
clp->cl_hostname, -status);
nfs4_end_drain_session(clp);
nfs4_clear_state_manager_bit(clp);
}
static int nfs4_run_state_manager(void *ptr)
{
struct nfs_client *clp = ptr;
allow_signal(SIGKILL);
nfs4_state_manager(clp);
nfs_put_client(clp);
module_put_and_exit(0);
return 0;
}
/*
* Local variables:
* c-basic-offset: 8
* End:
*/