deleg: return delegation before conflicting operations

new function nfs41_delegation_return() for synchronous delegation return.  uses a condition variable to wait if another thread is already returning the delegation
if nfs41_delegate_open() would conflict with a delegation, return it before sending the OPEN
return the delegation before sending LINK, RENAME, REMOVE, and SETATTR

all of this functionality is dependent on the preprocessor define DELEGATION_RETURN_ON_CONFLICT (on by default).  if not defined, nfs41_delegation_return() is a noop

Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
Casey Bodley 2011-07-07 13:51:21 -04:00 committed by unknown
parent 38259e0017
commit bc6471d981
6 changed files with 179 additions and 19 deletions

View file

@ -133,7 +133,7 @@ void nfs41_open_stateid_arg(
if (state->delegation.state) {
nfs41_delegation_state *deleg = state->delegation.state;
AcquireSRWLockShared(&deleg->lock);
if (!deleg->state.recalled) {
if (deleg->status == DELEGATION_GRANTED) {
arg->type = STATEID_DELEG_FILE;
memcpy(&arg->stateid, &deleg->state.stateid, sizeof(stateid4));
}
@ -668,6 +668,9 @@ static void cancel_open(IN nfs41_upcall *upcall)
} else if (args->created) {
const nfs41_component *name = &state->file.name;
/* break any delegations and truncate before REMOVE */
nfs41_delegation_return(state->session, &state->file,
OPEN_DELEGATE_WRITE, TRUE);
status = nfs41_remove(state->session, &state->parent, name);
if (status)
dprintf(1, "cancel_open: nfs41_remove() failed with %s\n",
@ -722,6 +725,10 @@ static int handle_close(nfs41_upcall *upcall)
create_silly_rename(&state->path, &state->file.fh, name);
}
/* break any delegations and truncate before REMOVE */
nfs41_delegation_return(state->session, &state->file,
OPEN_DELEGATE_WRITE, TRUE);
dprintf(1, "calling nfs41_remove for %s\n", name->name);
rm_status = nfs41_remove(state->session, &state->parent, name);
if (rm_status) {