diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 65337c0..5886fe1 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -306,7 +306,8 @@ out: static void open_delegation_return( IN nfs41_session *session, IN nfs41_path_fh *file, - IN open_delegation4 *delegation) + IN open_delegation4 *delegation, + IN bool_t try_recovery) { stateid_arg stateid; int status; @@ -321,7 +322,7 @@ static void open_delegation_return( stateid.type = STATEID_DELEG_FILE; memcpy(&stateid.stateid, &delegation->stateid, sizeof(stateid4)); - status = nfs41_delegreturn(session, file, &stateid, TRUE); + status = nfs41_delegreturn(session, file, &stateid, try_recovery); /* clear the delegation type returned by nfs41_open() */ delegation->type = OPEN_DELEGATE_NONE; @@ -331,14 +332,18 @@ static void open_update_cache( IN nfs41_session *session, IN nfs41_path_fh *parent, IN nfs41_path_fh *file, + IN bool_t try_recovery, IN open_delegation4 *delegation, + IN bool_t already_delegated, IN change_info4 *changeinfo, IN nfs41_getattr_res *dir_attrs, IN nfs41_getattr_res *file_attrs) { struct nfs41_name_cache *cache = session_name_cache(session); + enum open_delegation_type4 delegation_type = + already_delegated ? OPEN_DELEGATE_NONE : delegation->type; uint32_t status; - + /* update the attributes of the parent directory */ memcpy(&dir_attrs->info->attrmask, &dir_attrs->obj_attributes.attrmask, sizeof(bitmap4)); @@ -350,7 +355,7 @@ static void open_update_cache( retry_cache_insert: AcquireSRWLockShared(&file->path->lock); status = nfs41_name_cache_insert(cache, file->path->path, &file->name, - &file->fh, file_attrs->info, changeinfo, delegation->type); + &file->fh, file_attrs->info, changeinfo, delegation_type); ReleaseSRWLockShared(&file->path->lock); if (status == ERROR_TOO_MANY_OPEN_FILES) { @@ -364,7 +369,7 @@ retry_cache_insert: if (status && delegation->type != OPEN_DELEGATE_NONE) { /* if we can't make room in the cache, return this * delegation immediately to free resources on the server */ - open_delegation_return(session, file, delegation); + open_delegation_return(session, file, delegation, try_recovery); goto retry_cache_insert; } } @@ -403,6 +408,8 @@ int nfs41_open( nfs41_restorefh_res restorefh_res; nfs41_file_info tmp_info, dir_info; bool_t current_fh_is_dir; + bool_t already_delegated = delegation->type == OPEN_DELEGATE_READ + || delegation->type == OPEN_DELEGATE_WRITE; /* depending on the claim type, OPEN expects CURRENT_FH set * to either the parent directory, or to the file itself */ @@ -522,8 +529,8 @@ int nfs41_open( nfs41_superblock_space_changed(file->fh.superblock); /* update the name/attr cache with the results */ - open_update_cache(session, parent, file, delegation, - &open_res.resok4.cinfo, &pgetattr_res, &getattr_res); + open_update_cache(session, parent, file, try_recovery, delegation, + already_delegated, &open_res.resok4.cinfo, &pgetattr_res, &getattr_res); out: return status; } diff --git a/daemon/recovery.c b/daemon/recovery.c index 56c403b..7e3b77a 100644 --- a/daemon/recovery.c +++ b/daemon/recovery.c @@ -78,14 +78,13 @@ static int recover_open_grace( IN state_owner4 *owner, IN uint32_t access, IN uint32_t deny, - IN enum open_delegation_type4 delegate_type, OUT stateid4 *stateid, OUT open_delegation4 *delegation) { /* reclaim the open stateid with CLAIM_PREVIOUS */ open_claim4 claim; claim.claim = CLAIM_PREVIOUS; - claim.u.prev.delegate_type = delegate_type; + claim.u.prev.delegate_type = delegation->type; return nfs41_open(session, parent, file, owner, &claim, access, deny, OPEN4_NOCREATE, 0, 0, FALSE, stateid, delegation, NULL); @@ -98,14 +97,13 @@ static int recover_open_no_grace( IN state_owner4 *owner, IN uint32_t access, IN uint32_t deny, - IN enum open_delegation_type4 delegate_type, OUT stateid4 *stateid, OUT open_delegation4 *delegation) { open_claim4 claim; int status; - if (delegate_type != OPEN_DELEGATE_NONE) { + if (delegation->type != OPEN_DELEGATE_NONE) { /* attempt out-of-grace recovery with CLAIM_DELEGATE_PREV */ claim.claim = CLAIM_DELEGATE_PREV; claim.u.deleg_prev.filename = &file->name; @@ -125,9 +123,9 @@ static int recover_open_no_grace( claim.u.null.filename = &file->name; /* ask nicely for the delegation we had */ - if (delegate_type == OPEN_DELEGATE_READ) + if (delegation->type == OPEN_DELEGATE_READ) access |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG; - else if (delegate_type == OPEN_DELEGATE_WRITE) + else if (delegation->type == OPEN_DELEGATE_WRITE) access |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG; status = nfs41_open(session, parent, file, owner, @@ -144,7 +142,6 @@ static int recover_open( { open_delegation4 delegation = { 0 }; stateid4 stateid = { 0 }; - enum open_delegation_type4 delegate_type = OPEN_DELEGATE_NONE; int status = NFS4ERR_BADHANDLE; /* check for an associated delegation */ @@ -154,7 +151,7 @@ static int recover_open( if (deleg->revoked) { /* reclaim the delegation along with the open */ AcquireSRWLockShared(&deleg->lock); - delegate_type = deleg->state.type; + delegation.type = deleg->state.type; ReleaseSRWLockShared(&deleg->lock); } else if (deleg->state.recalled) { /* we'll need an open stateid regardless */ @@ -173,7 +170,7 @@ static int recover_open( if (*grace) status = recover_open_grace(session, &open->parent, &open->file, &open->owner, open->share_access, open->share_deny, - delegate_type, &stateid, &delegation); + &stateid, &delegation); else status = NFS4ERR_NO_GRACE; @@ -181,7 +178,7 @@ static int recover_open( *grace = FALSE; status = recover_open_no_grace(session, &open->parent, &open->file, &open->owner, open->share_access, open->share_deny, - delegate_type, &stateid, &delegation); + &stateid, &delegation); } if (status) goto out; @@ -276,15 +273,14 @@ static int recover_delegation_want( { deleg_claim4 claim; open_delegation4 delegation = { 0 }; - enum open_delegation_type4 delegate_type; uint32_t want_flags = 0; int status = NFS4_OK; AcquireSRWLockShared(&deleg->lock); - delegate_type = deleg->state.type; + delegation.type = deleg->state.type; ReleaseSRWLockShared(&deleg->lock); - if (delegate_type == OPEN_DELEGATE_READ) + if (delegation.type == OPEN_DELEGATE_READ) want_flags |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG; else want_flags |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG; @@ -292,7 +288,7 @@ static int recover_delegation_want( if (*grace) { /* recover the delegation with WANT_DELEGATION/CLAIM_PREVIOUS */ claim.claim = CLAIM_PREVIOUS; - claim.prev_delegate_type = delegate_type; + claim.prev_delegate_type = delegation.type; status = nfs41_want_delegation(session, &deleg->file, &claim, want_flags, FALSE, &delegation); @@ -336,13 +332,12 @@ static int recover_delegation_open( stateid_arg stateid; uint32_t access = OPEN4_SHARE_ACCESS_READ; uint32_t deny = OPEN4_SHARE_DENY_NONE; - enum open_delegation_type4 delegate_type = OPEN_DELEGATE_NONE; int status = NFS4_OK; /* choose the desired access mode based on delegation type */ AcquireSRWLockShared(&deleg->lock); - delegate_type = deleg->state.type; - if (delegate_type == OPEN_DELEGATE_WRITE) + delegation.type = deleg->state.type; + if (delegation.type == OPEN_DELEGATE_WRITE) access |= OPEN4_SHARE_ACCESS_WRITE | OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG; else access |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG; @@ -356,14 +351,14 @@ static int recover_delegation_open( if (*grace) status = recover_open_grace(session, &deleg->parent, &deleg->file, - &owner, access, deny, delegate_type, &stateid.stateid, &delegation); + &owner, access, deny, &stateid.stateid, &delegation); else status = NFS4ERR_NO_GRACE; if (status == NFS4ERR_NO_GRACE) { *grace = FALSE; status = recover_open_no_grace(session, &deleg->parent, &deleg->file, - &owner, access, deny, delegate_type, &stateid.stateid, &delegation); + &owner, access, deny, &stateid.stateid, &delegation); } if (status) goto out;