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:
Casey Bodley 2011-11-04 13:50:01 -04:00 committed by unknown
parent f988c89bf4
commit 68252b6522
2 changed files with 28 additions and 26 deletions

View file

@ -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;
}