namecache: delegation-related fixes
open_update_cache() wasn't retrying insert after the open_delegation_return() error case nfs41_name_cache_delegreturn() needs a check for if (attributes->delegated) to avoid an extra deref when the call to nfs41_name_cache_insert() failed added a TODO comment to nfs41_client_delegation_return_lru() for improvements to the naive algorithm Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
48fa809fc5
commit
0d86c68138
3 changed files with 19 additions and 17 deletions
|
|
@ -806,8 +806,13 @@ int nfs41_client_delegation_return_lru(
|
||||||
nfs41_delegation_state *state = NULL;
|
nfs41_delegation_state *state = NULL;
|
||||||
int status = NFS4ERR_BADHANDLE;
|
int status = NFS4ERR_BADHANDLE;
|
||||||
|
|
||||||
/* starting from the least recently opened, find a delegation
|
/* starting from the least recently opened, find and return
|
||||||
* that's not 'in use' and return it */
|
* the first delegation that's not 'in use' (currently open) */
|
||||||
|
|
||||||
|
/* TODO: use a more robust algorithm, taking into account:
|
||||||
|
* -number of total opens
|
||||||
|
* -time since last operation on an associated open, or
|
||||||
|
* -number of operations/second over last n seconds */
|
||||||
EnterCriticalSection(&client->state.lock);
|
EnterCriticalSection(&client->state.lock);
|
||||||
list_for_each(entry, &client->state.delegations) {
|
list_for_each(entry, &client->state.delegations) {
|
||||||
state = deleg_entry(entry);
|
state = deleg_entry(entry);
|
||||||
|
|
|
||||||
|
|
@ -78,14 +78,6 @@ static __inline bool_t is_delegation(
|
||||||
return type == OPEN_DELEGATE_READ || type == OPEN_DELEGATE_WRITE;
|
return type == OPEN_DELEGATE_READ || type == OPEN_DELEGATE_WRITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline bool_t deleg_entry_limit(
|
|
||||||
IN uint32_t delegations,
|
|
||||||
IN uint32_t max_entries)
|
|
||||||
{
|
|
||||||
/* limit the number of delegations to 50% of the cache capacity */
|
|
||||||
return delegations >= max_entries / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* attribute cache */
|
/* attribute cache */
|
||||||
struct attr_cache_entry {
|
struct attr_cache_entry {
|
||||||
|
|
@ -365,8 +357,9 @@ struct nfs41_name_cache {
|
||||||
struct list_entry exp_entries; /* list of entries by expiry */
|
struct list_entry exp_entries; /* list of entries by expiry */
|
||||||
uint32_t expiration;
|
uint32_t expiration;
|
||||||
uint32_t entries;
|
uint32_t entries;
|
||||||
uint32_t delegations;
|
|
||||||
uint32_t max_entries;
|
uint32_t max_entries;
|
||||||
|
uint32_t delegations;
|
||||||
|
uint32_t max_delegations;
|
||||||
SRWLOCK lock;
|
SRWLOCK lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -724,6 +717,7 @@ int nfs41_name_cache_create(
|
||||||
list_init(&cache->exp_entries);
|
list_init(&cache->exp_entries);
|
||||||
cache->expiration = NAME_CACHE_EXPIRATION;
|
cache->expiration = NAME_CACHE_EXPIRATION;
|
||||||
cache->max_entries = NAME_CACHE_MAX_ENTRIES;
|
cache->max_entries = NAME_CACHE_MAX_ENTRIES;
|
||||||
|
cache->max_delegations = NAME_CACHE_MAX_ENTRIES / 2;
|
||||||
InitializeSRWLock(&cache->lock);
|
InitializeSRWLock(&cache->lock);
|
||||||
|
|
||||||
/* allocate a pool of entries */
|
/* allocate a pool of entries */
|
||||||
|
|
@ -899,8 +893,8 @@ int nfs41_name_cache_insert(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* limit the number of delegations to prevent attr cache starvation */
|
/* limit the number of delegations to prevent attr cache starvation */
|
||||||
if (is_delegation(delegation) && deleg_entry_limit(
|
if (is_delegation(delegation) &&
|
||||||
cache->delegations, cache->max_entries)) {
|
cache->delegations >= cache->max_delegations) {
|
||||||
status = ERROR_TOO_MANY_OPEN_FILES;
|
status = ERROR_TOO_MANY_OPEN_FILES;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
@ -998,9 +992,11 @@ int nfs41_name_cache_delegreturn(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* release the reference from name_cache_entry_update() */
|
/* release the reference from name_cache_entry_update() */
|
||||||
|
if (attributes->delegated) {
|
||||||
attributes->delegated = FALSE;
|
attributes->delegated = FALSE;
|
||||||
attr_cache_entry_deref(&cache->attributes, attributes);
|
attr_cache_entry_deref(&cache->attributes, attributes);
|
||||||
cache->delegations--;
|
cache->delegations--;
|
||||||
|
}
|
||||||
status = NO_ERROR;
|
status = NO_ERROR;
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
|
|
|
||||||
|
|
@ -361,10 +361,11 @@ retry_cache_insert:
|
||||||
goto retry_cache_insert;
|
goto retry_cache_insert;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
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);
|
||||||
|
goto retry_cache_insert;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue