From 6c1c300a3b94054bdfad34a298d3aca86357fb4f Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Mon, 19 Dec 2011 16:03:33 -0500 Subject: [PATCH] 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 --- daemon/nfs41_compound.c | 36 +++++++--------------------- daemon/recovery.c | 52 ++++++++++++++++++++++++++++++++++++++--- daemon/recovery.h | 4 ++++ 3 files changed, 62 insertions(+), 30 deletions(-) diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index a57129d..10fd01d 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -150,7 +150,6 @@ int compound_encode_send_decode( int status, retry_count = 0, delayby = 0, secinfo_status; nfs41_sequence_args *args = (nfs41_sequence_args *) compound->args.argarray[0].arg; - bool_t client_state_lost = FALSE; uint32_t saved_sec_flavor; AUTH *saved_auth; int op1 = compound->args.argarray[0].op; @@ -218,14 +217,13 @@ retry: goto out; if (!nfs41_recovery_start_or_wait(session->client)) goto do_retry; - //try to create a new client + // try to create a new client status = nfs41_client_renew(session->client); nfs41_recovery_finish(session->client); 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; - goto out; } if (op1 == OP_CREATE_SESSION) { @@ -243,31 +241,15 @@ retry: goto out; if (!nfs41_recovery_start_or_wait(session->client)) goto do_retry; -restart_recovery: - //try to create a new session - status = nfs41_session_renew(session); - if (status == NFS4ERR_STALE_CLIENTID) { - client_state_lost = TRUE; - status = nfs41_client_renew(session->client); - if (status) { - 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); + // try to create a new session + status = nfs41_recover_session(session, FALSE); + + nfs41_recovery_finish(session->client); + if (status) { + eprintf("nfs41_recover_session() failed with %d\n", status); + status = ERROR_BAD_NET_RESP; 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; case NFS4ERR_EXPIRED: /* revoked by lease expiration */ diff --git a/daemon/recovery.c b/daemon/recovery.c index 1b8f343..5f90c69 100644 --- a/daemon/recovery.c +++ b/daemon/recovery.c @@ -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( IN nfs41_session *session, IN uint32_t flags) @@ -78,16 +108,32 @@ void nfs41_recover_sequence_flags( (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED | SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED | SEQ4_STATUS_ADMIN_STATE_REVOKED); + const uint32_t restarted = flags & + SEQ4_STATUS_RESTART_RECLAIM_NEEDED; /* no state recovery needed */ - if (revoked == 0) + if (revoked == 0 && restarted == 0) return; if (!nfs41_recovery_start_or_wait(session->client)) return; - /* free stateids and attempt to recover them */ - nfs41_client_state_revoked(session, session->client, revoked); + if (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); } diff --git a/daemon/recovery.h b/daemon/recovery.h index 583fb47..2b91c1b 100644 --- a/daemon/recovery.h +++ b/daemon/recovery.h @@ -39,6 +39,10 @@ void nfs41_recovery_finish( IN nfs41_client *client); +int nfs41_recover_session( + IN nfs41_session *session, + IN bool_t client_state_lost); + void nfs41_recover_sequence_flags( IN nfs41_session *session, IN uint32_t flags);