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 <cbodley@citi.umich.edu>
This commit is contained in:
parent
7240c69b5d
commit
d59d17c3b4
3 changed files with 38 additions and 5 deletions
|
|
@ -94,6 +94,8 @@ typedef struct __nfs41_open_state {
|
||||||
struct list_entry client_entry; /* entry in nfs41_client.opens */
|
struct list_entry client_entry; /* entry in nfs41_client.opens */
|
||||||
SRWLOCK lock;
|
SRWLOCK lock;
|
||||||
LONG ref_count;
|
LONG ref_count;
|
||||||
|
uint32_t share_access;
|
||||||
|
uint32_t share_deny;
|
||||||
} nfs41_open_state;
|
} nfs41_open_state;
|
||||||
|
|
||||||
typedef struct __nfs41_rpc_clnt {
|
typedef struct __nfs41_rpc_clnt {
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ int compound_encode_send_decode(
|
||||||
int status, retry_count = 0, delayby = 0;
|
int status, retry_count = 0, delayby = 0;
|
||||||
nfs41_sequence_args *args =
|
nfs41_sequence_args *args =
|
||||||
(nfs41_sequence_args *)compound->args.argarray[0].arg;
|
(nfs41_sequence_args *)compound->args.argarray[0].arg;
|
||||||
bool_t zero = 0;
|
bool_t zero = 0, client_state_lost = FALSE;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
/* send compound */
|
/* send compound */
|
||||||
|
|
@ -184,6 +184,7 @@ retry:
|
||||||
goto out_free_slot;
|
goto out_free_slot;
|
||||||
else if (status == 1)
|
else if (status == 1)
|
||||||
goto do_retry;
|
goto do_retry;
|
||||||
|
client_state_lost = TRUE;
|
||||||
status = nfs41_client_renew(session->client);
|
status = nfs41_client_renew(session->client);
|
||||||
if (status) {
|
if (status) {
|
||||||
eprintf("nfs41_exchange_id() failed with %d\n", status);
|
eprintf("nfs41_exchange_id() failed with %d\n", status);
|
||||||
|
|
@ -202,6 +203,7 @@ retry:
|
||||||
}
|
}
|
||||||
status = nfs41_session_renew(session);
|
status = nfs41_session_renew(session);
|
||||||
if (status == NFS4ERR_STALE_CLIENTID) {
|
if (status == NFS4ERR_STALE_CLIENTID) {
|
||||||
|
client_state_lost = TRUE;
|
||||||
status = nfs41_client_renew(session->client);
|
status = nfs41_client_renew(session->client);
|
||||||
if (status) {
|
if (status) {
|
||||||
eprintf("nfs41_exchange_id() failed with %d\n", status);
|
eprintf("nfs41_exchange_id() failed with %d\n", status);
|
||||||
|
|
@ -219,6 +221,34 @@ retry:
|
||||||
eprintf("nfs41_session_renew: failed with %d\n", status);
|
eprintf("nfs41_session_renew: failed with %d\n", status);
|
||||||
goto out;
|
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))
|
if (nfs41_renew_in_progress(session->client, NULL))
|
||||||
nfs41_renew_in_progress(session->client, &zero);
|
nfs41_renew_in_progress(session->client, &zero);
|
||||||
goto do_retry;
|
goto do_retry;
|
||||||
|
|
|
||||||
|
|
@ -395,9 +395,10 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
args->mode = info.mode;
|
args->mode = info.mode;
|
||||||
args->changeattr = info.change;
|
args->changeattr = info.change;
|
||||||
} else {
|
} 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);
|
status = map_disposition_2_nfsopen(args->disposition, status, &create, &upcall->last_error);
|
||||||
if (status)
|
if (status)
|
||||||
goto out_free_state;
|
goto out_free_state;
|
||||||
|
|
@ -414,8 +415,8 @@ static int handle_open(nfs41_upcall *upcall)
|
||||||
args->std_info.Directory = 1;
|
args->std_info.Directory = 1;
|
||||||
args->created = status == NFS4_OK ? TRUE : FALSE;
|
args->created = status == NFS4_OK ? TRUE : FALSE;
|
||||||
} else {
|
} else {
|
||||||
status = nfs41_open(state->session, allow, deny, create,
|
status = nfs41_open(state->session, state->share_access,
|
||||||
args->mode, state, &info);
|
state->share_deny, create, args->mode, state, &info);
|
||||||
|
|
||||||
if (status == NFS4_OK) {
|
if (status == NFS4_OK) {
|
||||||
/* add to the client's list of state for recovery */
|
/* add to the client's list of state for recovery */
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue