2023-06-20 15:33:42

by Keiichi Watanabe

[permalink] [raw]
Subject: [PATCH 0/3] Support negative dentry cache for FUSE and virtiofs


This patch series adds a new mount option called negative_dentry_timeout
for FUSE and virtio-fs filesystems. This option allows the kernel to cache
negative dentries, which are dentries that represent a non-existent file.
When this option is enabled, the kernel will skip FUSE_LOOKUP requests for
second and subsequent lookups to a non-existent file.

Unlike negative dentry caches on a normal filesystem such as ext4, the
kernel may need to refresh the cache for FUSE and virtio-fs filesystems.
This is because the kernel does not know when a FUSE server or a virtio-fs
device creates or deletes files. To address this, the new
negative_dentry_timeout option takes an expiration time for cache entries.
The appropriate timeout duration should be determined by considering how
often a FUSE server updates file paths and the amount of memory the kernel
can use for the cache.

As we evaluated the virtio-fs's performance on a guest Linux on crosvm
[1]'s virtiofs device[2], the `negative_dentry_timeout` option saved ~1
second per 10000 `stat` call against a non-existent path. The experiment
settings and results are as follows:

* Command to start VM with crosvm:
sudo crosvm run \
--disable-sandbox \
--cpus 1 \
--mem 2048 \
--rwroot debian.img \
--shared-dir \
/path/:my_virtiofs:type=fs:cache=always:timeout=3600 \
-p "console=hvc0 init=/bin/bash" \
vmlinux

* Mount command in the guest
Default:
$ mount -t virtiofs my_virtiofs ./workspace/
With negative dentry cache:
$ mount -t virtiofs -o negative_dentry_timeout=10 my_virtiofs ./workspace/

* Test commands
$ cd workspace
$ echo 3 > /proc/sys/vm/drop_caches
$ time for i in `seq 1 10000`; \
do stat non-existent.txt 2> /dev/null; \
done

* Results:
Default:
real 0m12.606s
user 0m3.624s
sys 0m7.756s

With `-o negative_dentry_timeout=10`:
real 0m11.276s
user 0m3.514s
sys 0m7.544s

[1]: https://crosvm.dev/book/
[2]: https://crosvm.dev/book/devices/fs.html


Keiichi Watanabe (3):
docs: virtiofs: Fix descriptions about virtiofs mount option
fuse: Add negative_dentry_timeout option
virtiofs: Add negative_dentry_timeout option

Documentation/filesystems/dax.rst | 1 +
Documentation/filesystems/fuse.rst | 6 ++++++
Documentation/filesystems/virtiofs.rst | 9 ++++++++-
fs/fuse/dir.c | 3 ++-
fs/fuse/fuse_i.h | 4 ++++
fs/fuse/inode.c | 12 +++++++++++-
fs/fuse/virtio_fs.c | 8 ++++++++
7 files changed, 40 insertions(+), 3 deletions(-)

--
2.41.0.185.g7c58973941-goog



2023-06-20 15:36:08

by Keiichi Watanabe

[permalink] [raw]
Subject: [PATCH 1/3] docs: virtiofs: Fix descriptions about virtiofs mount option

Since virtiofs and FUSE don't share mount options, fixes the
description. Also, explains DAX option as the only virtiofs-specific
option so far.

Signed-off-by: Keiichi Watanabe <[email protected]>
---

Documentation/filesystems/dax.rst | 1 +
Documentation/filesystems/virtiofs.rst | 5 ++++-
2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/Documentation/filesystems/dax.rst b/Documentation/filesystems/dax.rst
index c04609d8ee24..77c5d4550ecd 100644
--- a/Documentation/filesystems/dax.rst
+++ b/Documentation/filesystems/dax.rst
@@ -167,6 +167,7 @@ Setting the `FS_XFLAG_DAX` flag (specifically or through inheritance) occurs eve
if the underlying media does not support dax and/or the filesystem is
overridden with a mount option.

+.. _virtiofs-dax:

Enabling DAX on virtiofs
----------------------------
diff --git a/Documentation/filesystems/virtiofs.rst b/Documentation/filesystems/virtiofs.rst
index fd4d2484e949..fdec5a7840f7 100644
--- a/Documentation/filesystems/virtiofs.rst
+++ b/Documentation/filesystems/virtiofs.rst
@@ -43,7 +43,10 @@ Mount options
-------------

virtiofs supports general VFS mount options, for example, remount,
-ro, rw, context, etc. It also supports FUSE mount options.
+ro, rw, context, etc. Also, virtiofs has its own options.
+
+dax[=always,never,inode]
+ Enable direct access for files. See :ref:`virtiofs-dax`.

atime behavior
^^^^^^^^^^^^^^
--
2.41.0.185.g7c58973941-goog


2023-06-20 15:40:18

by Keiichi Watanabe

[permalink] [raw]
Subject: [PATCH 3/3] virtiofs: Add negative_dentry_timeout option

Add negative_dentry_timeout mount option to virtiofs to caching negative
dentry on the guest side. When the host virito-fs device has an exclusive
access to the file system and the machine has enough memory, one can
specify a long time as the timeout.

This option saves ~1 second per 10,000 stat request for non-existing paths.

Signed-off-by: Keiichi Watanabe <[email protected]>
---

Documentation/filesystems/virtiofs.rst | 4 ++++
fs/fuse/virtio_fs.c | 8 ++++++++
2 files changed, 12 insertions(+)

diff --git a/Documentation/filesystems/virtiofs.rst b/Documentation/filesystems/virtiofs.rst
index fdec5a7840f7..b045ef2223de 100644
--- a/Documentation/filesystems/virtiofs.rst
+++ b/Documentation/filesystems/virtiofs.rst
@@ -48,6 +48,10 @@ ro, rw, context, etc. Also, virtiofs has its own options.
dax[=always,never,inode]
Enable direct access for files. See :ref:`virtiofs-dax`.

+negative_dentry_timeout=N
+ Set the time in seconds to keep negative dentry cache. Same as the FUSE's
+ mount option.
+
atime behavior
^^^^^^^^^^^^^^

diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 4d8d4f16c727..bbbd840510f9 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -99,11 +99,13 @@ static const struct constant_table dax_param_enums[] = {
enum {
OPT_DAX,
OPT_DAX_ENUM,
+ OPT_NEGATIVE_DENTRY_TIMEOUT,
};

static const struct fs_parameter_spec virtio_fs_parameters[] = {
fsparam_flag("dax", OPT_DAX),
fsparam_enum("dax", OPT_DAX_ENUM, dax_param_enums),
+ fsparam_u32 ("negative_dentry_timeout", OPT_NEGATIVE_DENTRY_TIMEOUT),
{}
};

@@ -125,6 +127,9 @@ static int virtio_fs_parse_param(struct fs_context *fsc,
case OPT_DAX_ENUM:
ctx->dax_mode = result.uint_32;
break;
+ case OPT_NEGATIVE_DENTRY_TIMEOUT:
+ ctx->negative_dentry_timeout = result.uint_32;
+ break;
default:
return -EINVAL;
}
@@ -1416,6 +1421,7 @@ static int virtio_fs_get_tree(struct fs_context *fsc)
struct super_block *sb;
struct fuse_conn *fc = NULL;
struct fuse_mount *fm;
+ struct fuse_fs_context *ffc;
unsigned int virtqueue_size;
int err = -EIO;

@@ -1468,6 +1474,8 @@ static int virtio_fs_get_tree(struct fs_context *fsc)

sb->s_flags |= SB_ACTIVE;
}
+ ffc = fsc->fs_private;
+ fm->negative_dentry_timeout = ffc->negative_dentry_timeout;

WARN_ON(fsc->root);
fsc->root = dget(sb->s_root);
--
2.41.0.185.g7c58973941-goog