[Libguestfs] [PATCH libnbd v2 1/3] fuse: Enable multithread support

Richard W.M. Jones
Fri, 14 May 2021 09:06:11 -0000

This was much simpler than I though, merely changing fuse_loop ->
fuse_loop_mt.  FUSE itself will call our operations in parallel, so we
have to be careful about shared state.

Testing with fio shows this is about the same or a tiny bit slower
than before, which is not that surprising -- we are using the
synchronous API.  It should be possible to improve performance either
by issuing commands in parallel on the same handle (complicated) or by
using multi-conn.

test.fio contains:

  [global]
  filename=test.img
  bs=4k
  direct=1
  rw=read

  [job1]

  [job2]

  [job3]

  [job4]

Run the test:

  $ touch test.img
  $ nbdfuse test.img [ nbdkit memory 1G ] &
  $ fio test.fio
  $ fusermount3 -u test.img

Without this patch:

   READ: bw=239MiB/s (250MB/s), 59.6MiB/s-59.7MiB/s (62.5MB/s-62.6MB/s),
io=4096MiB (4295MB), run=17166-17167msec

With this patch:

   READ: bw=237MiB/s (248MB/s), 59.2MiB/s-59.2MiB/s (62.0MB/s-62.1MB/s),
io=4096MiB (4295MB), run=17303-17310msec
---
 fuse/nbdfuse.c    | 6 +++++-
 fuse/operations.c | 7 +++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/fuse/nbdfuse.c b/fuse/nbdfuse.c
index 3deef75..fa35080 100644
--- a/fuse/nbdfuse.c
+++ b/fuse/nbdfuse.c
@@ -151,6 +151,7 @@ main (int argc, char *argv[])
   int64_t ssize;
   const char *s;
   struct fuse_args fuse_args = FUSE_ARGS_INIT (0, NULL);
+  struct fuse_loop_config fuse_loop_config;
   FILE *fp;

   for (;;) {
@@ -475,7 +476,10 @@ main (int argc, char *argv[])
   }

   /* Enter the main loop. */
-  r = fuse_loop (fuse);
+  memset (&fuse_loop_config, 0, sizeof fuse_loop_config);
+  fuse_loop_config.clone_fd = 0;
+  fuse_loop_config.max_idle_threads = 10;
+  r = fuse_loop_mt (fuse, &fuse_loop_config);
   if (r < 0) {
     errno = -r;
     perror ("fuse_loop");
diff --git a/fuse/operations.c b/fuse/operations.c
index 2c38c6e..4da701e 100644
--- a/fuse/operations.c
+++ b/fuse/operations.c
@@ -16,6 +16,13 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */

+/* FUSE operations invoked by the kernel.
+ *
+ * Note these may be called in parallel from multiple threads, so any
+ * shared state needs to be read-only or else protected by mutexes.
+ * libnbd calls are OK.
+ */
+
 #include <config.h>

 #include <stdio.h>
--
2.31.1