All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jaco Kroon <jaco@uls.co.za>
To: Miklos Szeredi <miklos@szeredi.hu>,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Jaco Kroon <jaco@uls.co.za>
Subject: [PATCH] fuse: enable larger read buffers for readdir.
Date: Wed, 26 Jul 2023 12:59:37 +0200	[thread overview]
Message-ID: <20230726105953.843-1-jaco@uls.co.za> (raw)

Signed-off-by: Jaco Kroon <jaco@uls.co.za>
---
 fs/fuse/Kconfig   | 16 ++++++++++++++++
 fs/fuse/readdir.c | 42 ++++++++++++++++++++++++------------------
 2 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig
index 038ed0b9aaa5..0783f9ee5cd3 100644
--- a/fs/fuse/Kconfig
+++ b/fs/fuse/Kconfig
@@ -18,6 +18,22 @@ config FUSE_FS
 	  If you want to develop a userspace FS, or if you want to use
 	  a filesystem based on FUSE, answer Y or M.
 
+config FUSE_READDIR_ORDER
+	int
+	range 0 5
+	default 5
+	help
+		readdir performance varies greatly depending on the size of the read.
+		Larger buffers results in larger reads, thus fewer reads and higher
+		performance in return.
+
+		You may want to reduce this value on seriously constrained memory
+		systems where 128KiB (assuming 4KiB pages) cache pages is not ideal.
+
+		This value reprents the order of the number of pages to allocate (ie,
+		the shift value).  A value of 0 is thus 1 page (4KiB) where 5 is 32
+		pages (128KiB).
+
 config CUSE
 	tristate "Character device in Userspace support"
 	depends on FUSE_FS
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index dc603479b30e..98c62b623240 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -13,6 +13,12 @@
 #include <linux/pagemap.h>
 #include <linux/highmem.h>
 
+#define READDIR_PAGES_ORDER		CONFIG_FUSE_READDIR_ORDER
+#define READDIR_PAGES			(1 << READDIR_PAGES_ORDER)
+#define READDIR_PAGES_SIZE		(PAGE_SIZE << READDIR_PAGES_ORDER)
+#define READDIR_PAGES_MASK		(READDIR_PAGES_SIZE - 1)
+#define READDIR_PAGES_SHIFT		(PAGE_SHIFT + READDIR_PAGES_ORDER)
+
 static bool fuse_use_readdirplus(struct inode *dir, struct dir_context *ctx)
 {
 	struct fuse_conn *fc = get_fuse_conn(dir);
@@ -52,10 +58,10 @@ static void fuse_add_dirent_to_cache(struct file *file,
 	}
 	version = fi->rdc.version;
 	size = fi->rdc.size;
-	offset = size & ~PAGE_MASK;
-	index = size >> PAGE_SHIFT;
+	offset = size & ~READDIR_PAGES_MASK;
+	index = size >> READDIR_PAGES_SHIFT;
 	/* Dirent doesn't fit in current page?  Jump to next page. */
-	if (offset + reclen > PAGE_SIZE) {
+	if (offset + reclen > READDIR_PAGES_SIZE) {
 		index++;
 		offset = 0;
 	}
@@ -83,7 +89,7 @@ static void fuse_add_dirent_to_cache(struct file *file,
 	}
 	memcpy(addr + offset, dirent, reclen);
 	kunmap_local(addr);
-	fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen;
+	fi->rdc.size = (index << READDIR_PAGES_SHIFT) + offset + reclen;
 	fi->rdc.pos = dirent->off;
 unlock:
 	spin_unlock(&fi->rdc.lock);
@@ -104,7 +110,7 @@ static void fuse_readdir_cache_end(struct file *file, loff_t pos)
 	}
 
 	fi->rdc.cached = true;
-	end = ALIGN(fi->rdc.size, PAGE_SIZE);
+	end = ALIGN(fi->rdc.size, READDIR_PAGES_SIZE);
 	spin_unlock(&fi->rdc.lock);
 
 	/* truncate unused tail of cache */
@@ -328,25 +334,25 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
 	struct fuse_mount *fm = get_fuse_mount(inode);
 	struct fuse_io_args ia = {};
 	struct fuse_args_pages *ap = &ia.ap;
-	struct fuse_page_desc desc = { .length = PAGE_SIZE };
+	struct fuse_page_desc desc = { .length = READDIR_PAGES_SIZE };
 	u64 attr_version = 0;
 	bool locked;
 
-	page = alloc_page(GFP_KERNEL);
+	page = alloc_pages(GFP_KERNEL, READDIR_PAGES_ORDER);
 	if (!page)
 		return -ENOMEM;
 
 	plus = fuse_use_readdirplus(inode, ctx);
 	ap->args.out_pages = true;
-	ap->num_pages = 1;
+	ap->num_pages = READDIR_PAGES;
 	ap->pages = &page;
 	ap->descs = &desc;
 	if (plus) {
 		attr_version = fuse_get_attr_version(fm->fc);
-		fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE,
+		fuse_read_args_fill(&ia, file, ctx->pos, READDIR_PAGES_SIZE,
 				    FUSE_READDIRPLUS);
 	} else {
-		fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE,
+		fuse_read_args_fill(&ia, file, ctx->pos, READDIR_PAGES_SIZE,
 				    FUSE_READDIR);
 	}
 	locked = fuse_lock_inode(inode);
@@ -383,7 +389,7 @@ static enum fuse_parse_result fuse_parse_cache(struct fuse_file *ff,
 					       void *addr, unsigned int size,
 					       struct dir_context *ctx)
 {
-	unsigned int offset = ff->readdir.cache_off & ~PAGE_MASK;
+	unsigned int offset = ff->readdir.cache_off & ~READDIR_PAGES_MASK;
 	enum fuse_parse_result res = FOUND_NONE;
 
 	WARN_ON(offset >= size);
@@ -504,16 +510,16 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
 
 	WARN_ON(fi->rdc.size < ff->readdir.cache_off);
 
-	index = ff->readdir.cache_off >> PAGE_SHIFT;
+	index = ff->readdir.cache_off >> READDIR_PAGES_SHIFT;
 
-	if (index == (fi->rdc.size >> PAGE_SHIFT))
-		size = fi->rdc.size & ~PAGE_MASK;
+	if (index == (fi->rdc.size >> READDIR_PAGES_SHIFT))
+		size = fi->rdc.size & ~READDIR_PAGES_MASK;
 	else
-		size = PAGE_SIZE;
+		size = READDIR_PAGES_SIZE;
 	spin_unlock(&fi->rdc.lock);
 
 	/* EOF? */
-	if ((ff->readdir.cache_off & ~PAGE_MASK) == size)
+	if ((ff->readdir.cache_off & ~READDIR_PAGES_MASK) == size)
 		return 0;
 
 	page = find_get_page_flags(file->f_mapping, index,
@@ -559,9 +565,9 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
 	if (res == FOUND_ALL)
 		return 0;
 
-	if (size == PAGE_SIZE) {
+	if (size == READDIR_PAGES_SIZE) {
 		/* We hit end of page: skip to next page. */
-		ff->readdir.cache_off = ALIGN(ff->readdir.cache_off, PAGE_SIZE);
+		ff->readdir.cache_off = ALIGN(ff->readdir.cache_off, READDIR_PAGES_SIZE);
 		goto retry;
 	}
 
-- 
2.41.0


             reply	other threads:[~2023-07-26 11:22 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-26 10:59 Jaco Kroon [this message]
2023-07-26 11:43 ` [PATCH] fuse: enable larger read buffers for readdir Jaco Kroon
2023-07-26 13:53 ` Bernd Schubert
2023-07-26 15:26   ` Jaco Kroon
2023-07-26 15:30     ` Bernd Schubert
2023-07-26 15:45     ` Bernd Schubert
2023-07-26 17:23       ` Antonio SJ Musumeci
2023-07-26 18:25         ` Jaco Kroon
2023-07-27 15:21           ` Miklos Szeredi
2023-07-27 19:21           ` Miklos Szeredi
2023-07-27 19:43             ` Bernd Schubert
2023-07-28  8:42               ` Miklos Szeredi
2023-07-26 15:19 ` Randy Dunlap
2023-07-27  8:12 ` [PATCH] fuse: enable larger read buffers for readdir [v2] Jaco Kroon
2023-07-27 15:35   ` Miklos Szeredi
2023-07-27 16:58     ` Jaco Kroon
2023-07-27 19:17       ` Miklos Szeredi
2023-07-27 19:16     ` Bernd Schubert
2023-07-27 20:35     ` Bernd Schubert
2023-07-28  5:05       ` Jaco Kroon
2025-03-14 22:16   ` fuse: increase readdir() buffer size Jaco Kroon
2025-03-14 22:16     ` [PATCH 1/2] fs: Supply dir_context.count as readdir buffer size hint Jaco Kroon
2025-03-29  9:20       ` Christophe JAILLET
2025-03-30 14:27         ` Jaco Kroon
2025-03-14 22:16     ` [PATCH 2/2] fuse: Adjust readdir() buffer to requesting buffer size Jaco Kroon
2025-03-31 16:41       ` Joanne Koong
2025-03-31 20:43         ` Jaco Kroon
2025-03-31 21:48           ` Joanne Koong
2025-03-31 23:01             ` Joanne Koong
2025-03-28 10:15     ` fuse: increase readdir() " Jaco Kroon
2025-03-28 10:16       ` Bernd Schubert
2025-03-28 19:40       ` David Laight
2025-03-29  8:59         ` Jaco Kroon
2025-04-01 14:18     ` fuse: increase readdir() buffer size [v4] Jaco Kroon
2025-04-01 14:18       ` [PATCH 1/2] fs: Supply dir_context.count as readdir buffer size hint Jaco Kroon
2025-04-01 14:18       ` [PATCH 2/2] fuse: Adjust readdir() buffer to requesting buffer size Jaco Kroon
2025-04-01 14:40         ` Miklos Szeredi
2025-04-01 15:03           ` Jaco Kroon
2025-04-01 15:33             ` Miklos Szeredi
2025-04-02  7:54               ` Jaco Kroon
2025-04-02  8:18                 ` Miklos Szeredi
2025-04-02  8:52                   ` Jaco Kroon
2025-04-02  9:10                     ` Bernd Schubert
2025-04-02 11:13                       ` Jaco Kroon
2025-04-02 11:35                         ` Miklos Szeredi
2025-04-02 11:59                         ` Bernd Schubert
2025-04-08 14:19               ` Bernd Schubert
2025-04-09  7:12                 ` Jaco Kroon
2025-04-09  8:31                   ` Bernd Schubert
2025-04-09 15:03                     ` Jaco Kroon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230726105953.843-1-jaco@uls.co.za \
    --to=jaco@uls.co.za \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.