]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fuse: increase readdir buffer size
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 8 Apr 2025 13:14:20 +0000 (15:14 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 29 May 2025 10:31:24 +0000 (12:31 +0200)
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>
fs/fuse/readdir.c

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