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