name cache: bug fix for name_cache_search()

symptom: in certain cases, name_cache_find_or_create() was returning ERROR_FILE_EXISTS, which should never happen!

cause: the string comparisons in name_cache_search() and name_cache_insert() were returning different results when the argument to name_cache_search() is a) not null-terminated, and b) shorter than the other string.  this caused name_cache_search() to search the wrong branch of the rbtree and fail to find the component, while name_cache_insert() would correctly find it and return ERROR_FILE_EXISTS

fix: compare the string lengths before calling strncmp() to avoid comparing past the end of the component.  moved the comparisons to a separate component_cmp() function called by both name_cache_search() and name_cache_insert() to make sure they get the same result!

Signed-off-by: Casey Bodley <cbodley@umich.edu>
This commit is contained in:
Casey Bodley 2010-10-11 16:09:21 -04:00
parent c72007f076
commit d345a7b12e

View file

@ -531,6 +531,16 @@ static void name_cache_entry_invalidate(
name_cache_unlink(cache, entry); name_cache_unlink(cache, entry);
} }
static int component_cmp(
IN const char *lhs,
IN unsigned short lhs_len,
IN const char *rhs,
IN unsigned short rhs_len)
{
const int diff = rhs_len - lhs_len;
return diff ? diff : strncmp(lhs, rhs, lhs_len);
}
static struct name_cache_entry* name_cache_search( static struct name_cache_entry* name_cache_search(
IN struct nfs41_name_cache *cache, IN struct nfs41_name_cache *cache,
IN struct name_cache_entry *parent, IN struct name_cache_entry *parent,
@ -552,8 +562,9 @@ static struct name_cache_entry* name_cache_search(
while (node) { while (node) {
entry = rb_entry(node, struct name_cache_entry, rbnode); entry = rb_entry(node, struct name_cache_entry, rbnode);
result = strncmp(component->name, entry->component, result = component_cmp(component->name, component->len,
max(component->len, entry->component_len)); entry->component, entry->component_len);
if (result < 0) if (result < 0)
node = node->rb_left; node = node->rb_left;
else if (result > 0) else if (result > 0)
@ -658,7 +669,8 @@ static int name_cache_insert(
while (*node) { while (*node) {
current = rb_entry(*node, struct name_cache_entry, rbnode); current = rb_entry(*node, struct name_cache_entry, rbnode);
result = strcmp(entry->component, current->component); result = component_cmp(entry->component, entry->component_len,
current->component, current->component_len);
prev = *node; prev = *node;
if (result < 0) if (result < 0)