recovery: trigger recovery on RESTART_RECLAIM_NEEDED

adds a check for sequence flag SEQ4_STATUS_RESTART_RECLAIM_NEEDED in nfs41_recover_sequence_flags().  if other _STATE_REVOKED flags are set, call nfs41_client_state_revoked() as normal but follow it up with a RECLAIM_COMPLETE.  otherwise, reclaim all locks with nfs41_recover_client_state().  like other callers of nfs41_recover_client_state(), we need to handle BADSESSION errors because the recovery operations are sent with try_recovery=FALSE.  because this logic is similar to our default NFS4ERR_BADSESSION handling, i moved the common code into a new nfs41_recover_session() function in recovery.c

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2011-12-19 16:03:33 -05:00 committed by unknown
parent ab51beeb98
commit 6c1c300a3b
3 changed files with 62 additions and 30 deletions

View file

@ -150,7 +150,6 @@ int compound_encode_send_decode(
int status, retry_count = 0, delayby = 0, secinfo_status; int status, retry_count = 0, delayby = 0, secinfo_status;
nfs41_sequence_args *args = (nfs41_sequence_args *) nfs41_sequence_args *args = (nfs41_sequence_args *)
compound->args.argarray[0].arg; compound->args.argarray[0].arg;
bool_t client_state_lost = FALSE;
uint32_t saved_sec_flavor; uint32_t saved_sec_flavor;
AUTH *saved_auth; AUTH *saved_auth;
int op1 = compound->args.argarray[0].op; int op1 = compound->args.argarray[0].op;
@ -218,14 +217,13 @@ retry:
goto out; goto out;
if (!nfs41_recovery_start_or_wait(session->client)) if (!nfs41_recovery_start_or_wait(session->client))
goto do_retry; goto do_retry;
//try to create a new client // try to create a new client
status = nfs41_client_renew(session->client); status = nfs41_client_renew(session->client);
nfs41_recovery_finish(session->client); nfs41_recovery_finish(session->client);
if (status) { if (status) {
eprintf("nfs41_exchange_id() failed with %d\n", status); eprintf("nfs41_client_renew() failed with %d\n", status);
status = ERROR_BAD_NET_RESP; status = ERROR_BAD_NET_RESP;
goto out; goto out;
} }
if (op1 == OP_CREATE_SESSION) { if (op1 == OP_CREATE_SESSION) {
@ -243,31 +241,15 @@ retry:
goto out; goto out;
if (!nfs41_recovery_start_or_wait(session->client)) if (!nfs41_recovery_start_or_wait(session->client))
goto do_retry; goto do_retry;
restart_recovery: // try to create a new session
//try to create a new session status = nfs41_recover_session(session, FALSE);
status = nfs41_session_renew(session);
if (status == NFS4ERR_STALE_CLIENTID) { nfs41_recovery_finish(session->client);
client_state_lost = TRUE; if (status) {
status = nfs41_client_renew(session->client); eprintf("nfs41_recover_session() failed with %d\n", status);
if (status) { status = ERROR_BAD_NET_RESP;
eprintf("nfs41_exchange_id() failed with %d\n", status);
status = ERROR_BAD_NET_RESP;
nfs41_recovery_finish(session->client);
goto out;
}
goto restart_recovery;
} else if (status) {
eprintf("nfs41_session_renew: failed with %d\n", status);
nfs41_recovery_finish(session->client);
goto out; goto out;
} }
if (client_state_lost) {
/* do client state recovery */
status = nfs41_recover_client_state(session, session->client);
if (status == NFS4ERR_BADSESSION)
goto restart_recovery;
}
nfs41_recovery_finish(session->client);
goto do_retry; goto do_retry;
case NFS4ERR_EXPIRED: /* revoked by lease expiration */ case NFS4ERR_EXPIRED: /* revoked by lease expiration */

View file

@ -70,6 +70,36 @@ void nfs41_recovery_finish(
} }
/* session/client/state recovery */
int nfs41_recover_session(
IN nfs41_session *session,
IN bool_t client_state_lost)
{
enum nfsstat4 status = NFS4_OK;
restart_recovery:
/* recover the session */
status = nfs41_session_renew(session);
if (status == NFS4ERR_STALE_CLIENTID) {
/* recover the client */
client_state_lost = TRUE;
status = nfs41_client_renew(session->client);
if (status == NFS4_OK)
goto restart_recovery; /* resume session recovery */
eprintf("nfs41_client_renew() failed with %d\n", status);
} else if (status) {
eprintf("nfs41_session_renew() failed with %d\n", status);
} else if (client_state_lost) {
/* recover the client's state */
status = nfs41_recover_client_state(session, session->client);
if (status == NFS4ERR_BADSESSION)
goto restart_recovery;
}
return status;
}
void nfs41_recover_sequence_flags( void nfs41_recover_sequence_flags(
IN nfs41_session *session, IN nfs41_session *session,
IN uint32_t flags) IN uint32_t flags)
@ -78,16 +108,32 @@ void nfs41_recover_sequence_flags(
(SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED
| SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED
| SEQ4_STATUS_ADMIN_STATE_REVOKED); | SEQ4_STATUS_ADMIN_STATE_REVOKED);
const uint32_t restarted = flags &
SEQ4_STATUS_RESTART_RECLAIM_NEEDED;
/* no state recovery needed */ /* no state recovery needed */
if (revoked == 0) if (revoked == 0 && restarted == 0)
return; return;
if (!nfs41_recovery_start_or_wait(session->client)) if (!nfs41_recovery_start_or_wait(session->client))
return; return;
/* free stateids and attempt to recover them */ if (revoked) {
nfs41_client_state_revoked(session, session->client, revoked); /* free stateids and attempt to recover them */
nfs41_client_state_revoked(session, session->client, revoked);
/* if RESTART_RECLAIM_NEEDED is also set, just do RECLAIM_COMPLETE */
if (restarted) nfs41_reclaim_complete(session);
} else if (restarted) {
/* do server reboot state recovery */
uint32_t status = nfs41_recover_client_state(session, session->client);
if (status == NFS4ERR_BADSESSION) {
/* recover the session and finish state recovery */
nfs41_recover_session(session, TRUE);
}
}
nfs41_recovery_finish(session->client); nfs41_recovery_finish(session->client);
} }

View file

@ -39,6 +39,10 @@ void nfs41_recovery_finish(
IN nfs41_client *client); IN nfs41_client *client);
int nfs41_recover_session(
IN nfs41_session *session,
IN bool_t client_state_lost);
void nfs41_recover_sequence_flags( void nfs41_recover_sequence_flags(
IN nfs41_session *session, IN nfs41_session *session,
IN uint32_t flags); IN uint32_t flags);