NFS: Simplify struct nfs_cache_array_entry

We don't need to store a hash, so replace struct qstr with a simple
const char pointer and length.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Dave Wysochanski <dwysocha@redhat.com>
This commit is contained in:
Trond Myklebust 2020-11-01 19:17:29 -05:00
parent ed09222d65
commit a52a8a6ada
1 changed files with 25 additions and 21 deletions

View File

@ -133,7 +133,8 @@ nfs_closedir(struct inode *inode, struct file *filp)
struct nfs_cache_array_entry {
u64 cookie;
u64 ino;
struct qstr string;
const char *name;
unsigned int name_len;
unsigned char d_type;
};
@ -192,7 +193,7 @@ void nfs_readdir_clear_array(struct page *page)
array = kmap_atomic(page);
for (i = 0; i < array->size; i++)
kfree(array->array[i].string.name);
kfree(array->array[i].name);
nfs_readdir_array_init(array);
kunmap_atomic(array);
}
@ -213,20 +214,17 @@ static bool nfs_readdir_array_is_full(struct nfs_cache_array *array)
* when called by nfs_readdir_add_to_array, the strings will be freed in
* nfs_clear_readdir_array()
*/
static
int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
static const char *nfs_readdir_copy_name(const char *name, unsigned int len)
{
string->len = len;
string->name = kmemdup_nul(name, len, GFP_KERNEL);
if (string->name == NULL)
return -ENOMEM;
const char *ret = kmemdup_nul(name, len, GFP_KERNEL);
/*
* Avoid a kmemleak false positive. The pointer to the name is stored
* in a page cache page which kmemleak does not scan.
*/
kmemleak_not_leak(string->name);
string->hash = full_name_hash(NULL, name, len);
return 0;
if (ret != NULL)
kmemleak_not_leak(ret);
return ret;
}
/*
@ -249,27 +247,34 @@ static int nfs_readdir_array_can_expand(struct nfs_cache_array *array)
static
int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
{
struct nfs_cache_array *array = kmap(page);
struct nfs_cache_array *array;
struct nfs_cache_array_entry *cache_entry;
const char *name;
int ret;
name = nfs_readdir_copy_name(entry->name, entry->len);
if (!name)
return -ENOMEM;
array = kmap_atomic(page);
ret = nfs_readdir_array_can_expand(array);
if (ret)
if (ret) {
kfree(name);
goto out;
}
cache_entry = &array->array[array->size];
cache_entry->cookie = entry->prev_cookie;
cache_entry->ino = entry->ino;
cache_entry->d_type = entry->d_type;
ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
if (ret)
goto out;
cache_entry->name_len = entry->len;
cache_entry->name = name;
array->last_cookie = entry->cookie;
array->size++;
if (entry->eof != 0)
nfs_readdir_array_set_eof(array);
out:
kunmap(page);
kunmap_atomic(array);
return ret;
}
@ -413,9 +418,8 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des
if (printk_ratelimit()) {
pr_notice("NFS: directory %pD2 contains a readdir loop."
"Please contact your server vendor. "
"The file: %.*s has duplicate cookie %llu\n",
desc->file, array->array[i].string.len,
array->array[i].string.name, desc->dir_cookie);
"The file: %s has duplicate cookie %llu\n",
desc->file, array->array[i].name, desc->dir_cookie);
}
status = -ELOOP;
goto out;
@ -888,7 +892,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
struct nfs_cache_array_entry *ent;
ent = &array->array[i];
if (!dir_emit(desc->ctx, ent->string.name, ent->string.len,
if (!dir_emit(desc->ctx, ent->name, ent->name_len,
nfs_compat_user_ino64(ent->ino), ent->d_type)) {
desc->eof = true;
break;