From d59d17c3b448b0cd24af7e47d883c4ba66369886 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Tue, 16 Nov 2010 11:44:34 -0500 Subject: [PATCH] recovery: reclaim opens on client renewal after the client and session have been recovered, loop through the client's list of open state, calling nfs41_open_reclaim() and updating the stateid on success nfs41_open_state saves the share_access and share_deny fields from the initial open, for use with nfs41_open_reclaim() Signed-off-by: Casey Bodley --- daemon/nfs41.h | 2 ++ daemon/nfs41_compound.c | 32 +++++++++++++++++++++++++++++++- daemon/open.c | 9 +++++---- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/daemon/nfs41.h b/daemon/nfs41.h index 6ab2543..2294cf6 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -94,6 +94,8 @@ typedef struct __nfs41_open_state { struct list_entry client_entry; /* entry in nfs41_client.opens */ SRWLOCK lock; LONG ref_count; + uint32_t share_access; + uint32_t share_deny; } nfs41_open_state; typedef struct __nfs41_rpc_clnt { diff --git a/daemon/nfs41_compound.c b/daemon/nfs41_compound.c index fe116a9..b7d6651 100644 --- a/daemon/nfs41_compound.c +++ b/daemon/nfs41_compound.c @@ -117,7 +117,7 @@ int compound_encode_send_decode( int status, retry_count = 0, delayby = 0; nfs41_sequence_args *args = (nfs41_sequence_args *)compound->args.argarray[0].arg; - bool_t zero = 0; + bool_t zero = 0, client_state_lost = FALSE; retry: /* send compound */ @@ -184,6 +184,7 @@ retry: goto out_free_slot; else if (status == 1) goto do_retry; + client_state_lost = TRUE; status = nfs41_client_renew(session->client); if (status) { eprintf("nfs41_exchange_id() failed with %d\n", status); @@ -202,6 +203,7 @@ retry: } 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); @@ -219,6 +221,34 @@ retry: eprintf("nfs41_session_renew: failed with %d\n", status); goto out; } + /* do client state recovery */ + if (client_state_lost) { + struct client_state *state = &session->client->state; + struct list_entry *entry; + nfs41_open_state *open; + stateid4 stateid; + + EnterCriticalSection(&state->lock); + list_for_each(entry, &state->opens) { + open = list_container(entry, nfs41_open_state, client_entry); + status = nfs41_open_reclaim(session, &open->parent, &open->file, + &open->owner, open->share_access, open->share_deny, + &stateid); + if (status == NFS4_OK) { + /* update the open's stateid under lock */ + AcquireSRWLockExclusive(&open->lock); + memcpy(&open->stateid, &stateid, sizeof(stateid4)); + ReleaseSRWLockExclusive(&open->lock); + } + } + LeaveCriticalSection(&state->lock); + + /* send reclaim_complete, but don't fail on errors */ + status = nfs41_reclaim_complete(session); + if (status && status == NFS4ERR_NOTSUPP) + eprintf("nfs41_reclaim_complete() failed with %s\n", + nfs_error_string(status)); + } if (nfs41_renew_in_progress(session->client, NULL)) nfs41_renew_in_progress(session->client, &zero); goto do_retry; diff --git a/daemon/open.c b/daemon/open.c index 6de0469..96798aa 100644 --- a/daemon/open.c +++ b/daemon/open.c @@ -395,9 +395,10 @@ static int handle_open(nfs41_upcall *upcall) args->mode = info.mode; args->changeattr = info.change; } else { - uint32_t allow = 0, deny = 0, create = 0; + uint32_t create = 0; - map_access_2_allowdeny(args->access_mask, args->access_mode, &allow, &deny); + map_access_2_allowdeny(args->access_mask, args->access_mode, + &state->share_access, &state->share_deny); status = map_disposition_2_nfsopen(args->disposition, status, &create, &upcall->last_error); if (status) goto out_free_state; @@ -414,8 +415,8 @@ static int handle_open(nfs41_upcall *upcall) args->std_info.Directory = 1; args->created = status == NFS4_OK ? TRUE : FALSE; } else { - status = nfs41_open(state->session, allow, deny, create, - args->mode, state, &info); + status = nfs41_open(state->session, state->share_access, + state->share_deny, create, args->mode, state, &info); if (status == NFS4_OK) { /* add to the client's list of state for recovery */