recovery: reboot recovery of delegation stateids
recover_client_state() flags all delegations as revoked before starting open state recovery. if recover_open() finds that its delegation is revoked, it attempts to recover it using CLAIM_PREVIOUS. if its delegation has already been reclaimed by another open, it can skip reclaiming the open stateid (provided it has no byte-range locks to reclaim). after all opens have been reclaimed, any delegations still marked 'revoked' are passed to recover_delegation(). recover_delegation() also uses CLAIM_PREVIOUS (or CLAIM_NULL outside of the grace period) to reclaim the delegation, but has to throw away the open stateid with CLOSE added a try_recovery argument to nfs41_delegreturn() and nfs41_delegation_granted(), so it can be called by recover_open() if OPEN grants an unexpected open Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
3734527757
commit
4f47ae9a37
7 changed files with 228 additions and 32 deletions
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
/* allocation and reference counting */
|
||||
static int delegation_create(
|
||||
IN const nfs41_path_fh *parent,
|
||||
IN const nfs41_path_fh *file,
|
||||
IN const open_delegation4 *delegation,
|
||||
OUT nfs41_delegation_state **deleg_out)
|
||||
|
|
@ -46,9 +47,15 @@ static int delegation_create(
|
|||
}
|
||||
|
||||
memcpy(&state->state, delegation, sizeof(open_delegation4));
|
||||
|
||||
abs_path_copy(&state->path, file->path);
|
||||
path_fh_init(&state->file, &state->path);
|
||||
fh_copy(&state->file.fh, &file->fh);
|
||||
path_fh_init(&state->parent, &state->path);
|
||||
last_component(state->path.path, state->file.name.name,
|
||||
&state->parent.name);
|
||||
fh_copy(&state->parent.fh, &parent->fh);
|
||||
|
||||
list_init(&state->client_entry);
|
||||
state->status = DELEGATION_GRANTED;
|
||||
InitializeSRWLock(&state->lock);
|
||||
|
|
@ -132,7 +139,8 @@ static void delegation_return(
|
|||
|
||||
/* TODO: flush data and metadata before returning delegation */
|
||||
|
||||
nfs41_delegreturn(client->session, &deleg->file, &deleg->state.stateid);
|
||||
nfs41_delegreturn(client->session, &deleg->file,
|
||||
&deleg->state.stateid, TRUE);
|
||||
|
||||
/* remove from the client's list */
|
||||
EnterCriticalSection(&client->state.lock);
|
||||
|
|
@ -164,21 +172,25 @@ static void delegation_return(
|
|||
/* open delegation */
|
||||
int nfs41_delegation_granted(
|
||||
IN nfs41_session *session,
|
||||
IN nfs41_path_fh *parent,
|
||||
IN nfs41_path_fh *file,
|
||||
IN open_delegation4 *delegation,
|
||||
IN bool_t try_recovery,
|
||||
OUT nfs41_delegation_state **deleg_out)
|
||||
{
|
||||
nfs41_client *client = session->client;
|
||||
nfs41_delegation_state *state;
|
||||
int status = NO_ERROR;
|
||||
|
||||
if (delegation->recalled ||
|
||||
delegation->type == OPEN_DELEGATE_NONE ||
|
||||
delegation->type == OPEN_DELEGATE_NONE_EXT)
|
||||
if (delegation->type != OPEN_DELEGATE_READ &&
|
||||
delegation->type != OPEN_DELEGATE_WRITE)
|
||||
goto out;
|
||||
|
||||
if (delegation->recalled)
|
||||
goto out_return;
|
||||
|
||||
/* allocate the delegation state */
|
||||
status = delegation_create(file, delegation, &state);
|
||||
status = delegation_create(parent, file, delegation, &state);
|
||||
if (status)
|
||||
goto out_return;
|
||||
|
||||
|
|
@ -194,7 +206,7 @@ out:
|
|||
return status;
|
||||
|
||||
out_return: /* return the delegation on failure */
|
||||
nfs41_delegreturn(session, file, &delegation->stateid);
|
||||
nfs41_delegreturn(session, file, &delegation->stateid, try_recovery);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -439,7 +451,7 @@ int nfs41_delegation_return(
|
|||
}
|
||||
} else {
|
||||
/* the delegation is being returned, wait for it to finish */
|
||||
while (deleg->status != DELEGATION_RETURNING)
|
||||
while (deleg->status != DELEGATION_RETURNED)
|
||||
SleepConditionVariableSRW(&deleg->cond, &deleg->lock, INFINITE, 0);
|
||||
status = NFS4ERR_BADHANDLE;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue