fuse: increase readdir buffer size

Increase the buffer size to the count requested by userspace.  This
improves performance.

Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
This commit is contained in:
Miklos Szeredi 2025-04-08 15:14:20 +02:00 committed by Miklos Szeredi
parent 467e245d47
commit dabb903910
1 changed files with 14 additions and 19 deletions

View File

@ -335,35 +335,32 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
{ {
int plus; int plus;
ssize_t res; ssize_t res;
struct folio *folio;
struct inode *inode = file_inode(file); struct inode *inode = file_inode(file);
struct fuse_mount *fm = get_fuse_mount(inode); struct fuse_mount *fm = get_fuse_mount(inode);
struct fuse_conn *fc = fm->fc;
struct fuse_io_args ia = {}; struct fuse_io_args ia = {};
struct fuse_args_pages *ap = &ia.ap; struct fuse_args *args = &ia.ap.args;
struct fuse_folio_desc desc = { .length = PAGE_SIZE }; void *buf;
size_t bufsize = clamp((unsigned int) ctx->count, PAGE_SIZE, fc->max_pages << PAGE_SHIFT);
u64 attr_version = 0, evict_ctr = 0; u64 attr_version = 0, evict_ctr = 0;
bool locked; bool locked;
folio = folio_alloc(GFP_KERNEL, 0); buf = kvmalloc(bufsize, GFP_KERNEL);
if (!folio) if (!buf)
return -ENOMEM; return -ENOMEM;
args->out_args[0].value = buf;
plus = fuse_use_readdirplus(inode, ctx); plus = fuse_use_readdirplus(inode, ctx);
ap->args.out_pages = true;
ap->num_folios = 1;
ap->folios = &folio;
ap->descs = &desc;
if (plus) { if (plus) {
attr_version = fuse_get_attr_version(fm->fc); attr_version = fuse_get_attr_version(fm->fc);
evict_ctr = fuse_get_evict_ctr(fm->fc); evict_ctr = fuse_get_evict_ctr(fm->fc);
fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE, fuse_read_args_fill(&ia, file, ctx->pos, bufsize, FUSE_READDIRPLUS);
FUSE_READDIRPLUS);
} else { } else {
fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE, fuse_read_args_fill(&ia, file, ctx->pos, bufsize, FUSE_READDIR);
FUSE_READDIR);
} }
locked = fuse_lock_inode(inode); locked = fuse_lock_inode(inode);
res = fuse_simple_request(fm, &ap->args); res = fuse_simple_request(fm, args);
fuse_unlock_inode(inode, locked); fuse_unlock_inode(inode, locked);
if (res >= 0) { if (res >= 0) {
if (!res) { if (!res) {
@ -372,16 +369,14 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
if (ff->open_flags & FOPEN_CACHE_DIR) if (ff->open_flags & FOPEN_CACHE_DIR)
fuse_readdir_cache_end(file, ctx->pos); fuse_readdir_cache_end(file, ctx->pos);
} else if (plus) { } else if (plus) {
res = parse_dirplusfile(folio_address(folio), res, res = parse_dirplusfile(buf, res, file, ctx, attr_version,
file, ctx, attr_version,
evict_ctr); evict_ctr);
} else { } else {
res = parse_dirfile(folio_address(folio), res, file, res = parse_dirfile(buf, res, file, ctx);
ctx);
} }
} }
folio_put(folio); kvfree(buf);
fuse_invalidate_atime(inode); fuse_invalidate_atime(inode);
return res; return res;
} }