recovery: avoid delegation_return_lru() on delegation recovery
the namecache/delegation feedback code in nfs41_ops.c:open_update_cache() is interfering with delegation recovery. if its call to nfs41_name_cache_insert() fails with ERROR_TOO_MANY_OPEN_FILES, the delegation is returned instead of being recovered. this shouldn't happen during recovery, because we're replacing a delegation rather than adding a new one nfs41_open() now remembers whether we already had a delegation. if we did, open_update_cache() will pass OPEN_DELEGATE_NONE to nfs41_name_cache_insert() to prevent it from returning ERROR_TOO_MANY_OPEN_FILES. if we didn't already have a delegation, the nfs41_delegreturn() needs to be called with the same try_recovery flag from nfs41_open() Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
f988c89bf4
commit
68252b6522
2 changed files with 28 additions and 26 deletions
|
|
@ -306,7 +306,8 @@ out:
|
||||||
static void open_delegation_return(
|
static void open_delegation_return(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
IN nfs41_path_fh *file,
|
IN nfs41_path_fh *file,
|
||||||
IN open_delegation4 *delegation)
|
IN open_delegation4 *delegation,
|
||||||
|
IN bool_t try_recovery)
|
||||||
{
|
{
|
||||||
stateid_arg stateid;
|
stateid_arg stateid;
|
||||||
int status;
|
int status;
|
||||||
|
|
@ -321,7 +322,7 @@ static void open_delegation_return(
|
||||||
stateid.type = STATEID_DELEG_FILE;
|
stateid.type = STATEID_DELEG_FILE;
|
||||||
memcpy(&stateid.stateid, &delegation->stateid, sizeof(stateid4));
|
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() */
|
/* clear the delegation type returned by nfs41_open() */
|
||||||
delegation->type = OPEN_DELEGATE_NONE;
|
delegation->type = OPEN_DELEGATE_NONE;
|
||||||
|
|
@ -331,12 +332,16 @@ static void open_update_cache(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
IN nfs41_path_fh *parent,
|
IN nfs41_path_fh *parent,
|
||||||
IN nfs41_path_fh *file,
|
IN nfs41_path_fh *file,
|
||||||
|
IN bool_t try_recovery,
|
||||||
IN open_delegation4 *delegation,
|
IN open_delegation4 *delegation,
|
||||||
|
IN bool_t already_delegated,
|
||||||
IN change_info4 *changeinfo,
|
IN change_info4 *changeinfo,
|
||||||
IN nfs41_getattr_res *dir_attrs,
|
IN nfs41_getattr_res *dir_attrs,
|
||||||
IN nfs41_getattr_res *file_attrs)
|
IN nfs41_getattr_res *file_attrs)
|
||||||
{
|
{
|
||||||
struct nfs41_name_cache *cache = session_name_cache(session);
|
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;
|
uint32_t status;
|
||||||
|
|
||||||
/* update the attributes of the parent directory */
|
/* update the attributes of the parent directory */
|
||||||
|
|
@ -350,7 +355,7 @@ static void open_update_cache(
|
||||||
retry_cache_insert:
|
retry_cache_insert:
|
||||||
AcquireSRWLockShared(&file->path->lock);
|
AcquireSRWLockShared(&file->path->lock);
|
||||||
status = nfs41_name_cache_insert(cache, file->path->path, &file->name,
|
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);
|
ReleaseSRWLockShared(&file->path->lock);
|
||||||
|
|
||||||
if (status == ERROR_TOO_MANY_OPEN_FILES) {
|
if (status == ERROR_TOO_MANY_OPEN_FILES) {
|
||||||
|
|
@ -364,7 +369,7 @@ retry_cache_insert:
|
||||||
if (status && delegation->type != OPEN_DELEGATE_NONE) {
|
if (status && delegation->type != OPEN_DELEGATE_NONE) {
|
||||||
/* if we can't make room in the cache, return this
|
/* if we can't make room in the cache, return this
|
||||||
* delegation immediately to free resources on the server */
|
* 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;
|
goto retry_cache_insert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,6 +408,8 @@ int nfs41_open(
|
||||||
nfs41_restorefh_res restorefh_res;
|
nfs41_restorefh_res restorefh_res;
|
||||||
nfs41_file_info tmp_info, dir_info;
|
nfs41_file_info tmp_info, dir_info;
|
||||||
bool_t current_fh_is_dir;
|
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
|
/* depending on the claim type, OPEN expects CURRENT_FH set
|
||||||
* to either the parent directory, or to the file itself */
|
* to either the parent directory, or to the file itself */
|
||||||
|
|
@ -522,8 +529,8 @@ int nfs41_open(
|
||||||
nfs41_superblock_space_changed(file->fh.superblock);
|
nfs41_superblock_space_changed(file->fh.superblock);
|
||||||
|
|
||||||
/* update the name/attr cache with the results */
|
/* update the name/attr cache with the results */
|
||||||
open_update_cache(session, parent, file, delegation,
|
open_update_cache(session, parent, file, try_recovery, delegation,
|
||||||
&open_res.resok4.cinfo, &pgetattr_res, &getattr_res);
|
already_delegated, &open_res.resok4.cinfo, &pgetattr_res, &getattr_res);
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,13 @@ static int recover_open_grace(
|
||||||
IN state_owner4 *owner,
|
IN state_owner4 *owner,
|
||||||
IN uint32_t access,
|
IN uint32_t access,
|
||||||
IN uint32_t deny,
|
IN uint32_t deny,
|
||||||
IN enum open_delegation_type4 delegate_type,
|
|
||||||
OUT stateid4 *stateid,
|
OUT stateid4 *stateid,
|
||||||
OUT open_delegation4 *delegation)
|
OUT open_delegation4 *delegation)
|
||||||
{
|
{
|
||||||
/* reclaim the open stateid with CLAIM_PREVIOUS */
|
/* reclaim the open stateid with CLAIM_PREVIOUS */
|
||||||
open_claim4 claim;
|
open_claim4 claim;
|
||||||
claim.claim = CLAIM_PREVIOUS;
|
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,
|
return nfs41_open(session, parent, file, owner, &claim, access, deny,
|
||||||
OPEN4_NOCREATE, 0, 0, FALSE, stateid, delegation, NULL);
|
OPEN4_NOCREATE, 0, 0, FALSE, stateid, delegation, NULL);
|
||||||
|
|
@ -98,14 +97,13 @@ static int recover_open_no_grace(
|
||||||
IN state_owner4 *owner,
|
IN state_owner4 *owner,
|
||||||
IN uint32_t access,
|
IN uint32_t access,
|
||||||
IN uint32_t deny,
|
IN uint32_t deny,
|
||||||
IN enum open_delegation_type4 delegate_type,
|
|
||||||
OUT stateid4 *stateid,
|
OUT stateid4 *stateid,
|
||||||
OUT open_delegation4 *delegation)
|
OUT open_delegation4 *delegation)
|
||||||
{
|
{
|
||||||
open_claim4 claim;
|
open_claim4 claim;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (delegate_type != OPEN_DELEGATE_NONE) {
|
if (delegation->type != OPEN_DELEGATE_NONE) {
|
||||||
/* attempt out-of-grace recovery with CLAIM_DELEGATE_PREV */
|
/* attempt out-of-grace recovery with CLAIM_DELEGATE_PREV */
|
||||||
claim.claim = CLAIM_DELEGATE_PREV;
|
claim.claim = CLAIM_DELEGATE_PREV;
|
||||||
claim.u.deleg_prev.filename = &file->name;
|
claim.u.deleg_prev.filename = &file->name;
|
||||||
|
|
@ -125,9 +123,9 @@ static int recover_open_no_grace(
|
||||||
claim.u.null.filename = &file->name;
|
claim.u.null.filename = &file->name;
|
||||||
|
|
||||||
/* ask nicely for the delegation we had */
|
/* 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;
|
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;
|
access |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
||||||
|
|
||||||
status = nfs41_open(session, parent, file, owner,
|
status = nfs41_open(session, parent, file, owner,
|
||||||
|
|
@ -144,7 +142,6 @@ static int recover_open(
|
||||||
{
|
{
|
||||||
open_delegation4 delegation = { 0 };
|
open_delegation4 delegation = { 0 };
|
||||||
stateid4 stateid = { 0 };
|
stateid4 stateid = { 0 };
|
||||||
enum open_delegation_type4 delegate_type = OPEN_DELEGATE_NONE;
|
|
||||||
int status = NFS4ERR_BADHANDLE;
|
int status = NFS4ERR_BADHANDLE;
|
||||||
|
|
||||||
/* check for an associated delegation */
|
/* check for an associated delegation */
|
||||||
|
|
@ -154,7 +151,7 @@ static int recover_open(
|
||||||
if (deleg->revoked) {
|
if (deleg->revoked) {
|
||||||
/* reclaim the delegation along with the open */
|
/* reclaim the delegation along with the open */
|
||||||
AcquireSRWLockShared(&deleg->lock);
|
AcquireSRWLockShared(&deleg->lock);
|
||||||
delegate_type = deleg->state.type;
|
delegation.type = deleg->state.type;
|
||||||
ReleaseSRWLockShared(&deleg->lock);
|
ReleaseSRWLockShared(&deleg->lock);
|
||||||
} else if (deleg->state.recalled) {
|
} else if (deleg->state.recalled) {
|
||||||
/* we'll need an open stateid regardless */
|
/* we'll need an open stateid regardless */
|
||||||
|
|
@ -173,7 +170,7 @@ static int recover_open(
|
||||||
if (*grace)
|
if (*grace)
|
||||||
status = recover_open_grace(session, &open->parent, &open->file,
|
status = recover_open_grace(session, &open->parent, &open->file,
|
||||||
&open->owner, open->share_access, open->share_deny,
|
&open->owner, open->share_access, open->share_deny,
|
||||||
delegate_type, &stateid, &delegation);
|
&stateid, &delegation);
|
||||||
else
|
else
|
||||||
status = NFS4ERR_NO_GRACE;
|
status = NFS4ERR_NO_GRACE;
|
||||||
|
|
||||||
|
|
@ -181,7 +178,7 @@ static int recover_open(
|
||||||
*grace = FALSE;
|
*grace = FALSE;
|
||||||
status = recover_open_no_grace(session, &open->parent, &open->file,
|
status = recover_open_no_grace(session, &open->parent, &open->file,
|
||||||
&open->owner, open->share_access, open->share_deny,
|
&open->owner, open->share_access, open->share_deny,
|
||||||
delegate_type, &stateid, &delegation);
|
&stateid, &delegation);
|
||||||
}
|
}
|
||||||
if (status)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
@ -276,15 +273,14 @@ static int recover_delegation_want(
|
||||||
{
|
{
|
||||||
deleg_claim4 claim;
|
deleg_claim4 claim;
|
||||||
open_delegation4 delegation = { 0 };
|
open_delegation4 delegation = { 0 };
|
||||||
enum open_delegation_type4 delegate_type;
|
|
||||||
uint32_t want_flags = 0;
|
uint32_t want_flags = 0;
|
||||||
int status = NFS4_OK;
|
int status = NFS4_OK;
|
||||||
|
|
||||||
AcquireSRWLockShared(&deleg->lock);
|
AcquireSRWLockShared(&deleg->lock);
|
||||||
delegate_type = deleg->state.type;
|
delegation.type = deleg->state.type;
|
||||||
ReleaseSRWLockShared(&deleg->lock);
|
ReleaseSRWLockShared(&deleg->lock);
|
||||||
|
|
||||||
if (delegate_type == OPEN_DELEGATE_READ)
|
if (delegation.type == OPEN_DELEGATE_READ)
|
||||||
want_flags |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG;
|
want_flags |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG;
|
||||||
else
|
else
|
||||||
want_flags |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
want_flags |= OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
||||||
|
|
@ -292,7 +288,7 @@ static int recover_delegation_want(
|
||||||
if (*grace) {
|
if (*grace) {
|
||||||
/* recover the delegation with WANT_DELEGATION/CLAIM_PREVIOUS */
|
/* recover the delegation with WANT_DELEGATION/CLAIM_PREVIOUS */
|
||||||
claim.claim = 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,
|
status = nfs41_want_delegation(session, &deleg->file, &claim,
|
||||||
want_flags, FALSE, &delegation);
|
want_flags, FALSE, &delegation);
|
||||||
|
|
@ -336,13 +332,12 @@ static int recover_delegation_open(
|
||||||
stateid_arg stateid;
|
stateid_arg stateid;
|
||||||
uint32_t access = OPEN4_SHARE_ACCESS_READ;
|
uint32_t access = OPEN4_SHARE_ACCESS_READ;
|
||||||
uint32_t deny = OPEN4_SHARE_DENY_NONE;
|
uint32_t deny = OPEN4_SHARE_DENY_NONE;
|
||||||
enum open_delegation_type4 delegate_type = OPEN_DELEGATE_NONE;
|
|
||||||
int status = NFS4_OK;
|
int status = NFS4_OK;
|
||||||
|
|
||||||
/* choose the desired access mode based on delegation type */
|
/* choose the desired access mode based on delegation type */
|
||||||
AcquireSRWLockShared(&deleg->lock);
|
AcquireSRWLockShared(&deleg->lock);
|
||||||
delegate_type = deleg->state.type;
|
delegation.type = deleg->state.type;
|
||||||
if (delegate_type == OPEN_DELEGATE_WRITE)
|
if (delegation.type == OPEN_DELEGATE_WRITE)
|
||||||
access |= OPEN4_SHARE_ACCESS_WRITE | OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
access |= OPEN4_SHARE_ACCESS_WRITE | OPEN4_SHARE_ACCESS_WANT_WRITE_DELEG;
|
||||||
else
|
else
|
||||||
access |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG;
|
access |= OPEN4_SHARE_ACCESS_WANT_READ_DELEG;
|
||||||
|
|
@ -356,14 +351,14 @@ static int recover_delegation_open(
|
||||||
|
|
||||||
if (*grace)
|
if (*grace)
|
||||||
status = recover_open_grace(session, &deleg->parent, &deleg->file,
|
status = recover_open_grace(session, &deleg->parent, &deleg->file,
|
||||||
&owner, access, deny, delegate_type, &stateid.stateid, &delegation);
|
&owner, access, deny, &stateid.stateid, &delegation);
|
||||||
else
|
else
|
||||||
status = NFS4ERR_NO_GRACE;
|
status = NFS4ERR_NO_GRACE;
|
||||||
|
|
||||||
if (status == NFS4ERR_NO_GRACE) {
|
if (status == NFS4ERR_NO_GRACE) {
|
||||||
*grace = FALSE;
|
*grace = FALSE;
|
||||||
status = recover_open_no_grace(session, &deleg->parent, &deleg->file,
|
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)
|
if (status)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue