2023-06-20 15:33:41

by Keiichi Watanabe

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

Add `negative_dentry_timeout` mount option for FUSE to cache negative
dentries for the specified duration.
With this option enabled, second and subsequent lookups to non-existent
files can be omitted.

A user needs to specify how often each negative_dentry cache should be
refreshed. This is because the kernel has no idea when a FUSE server
creates or deletes files, unlike normal filesystems such as ext4 where
all of file operations are managed by the kernel.
The appropriate timeout duration should be determined by considering how
often a FUSE server update file paths and the amount of memory the
kernel can use the cache.

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

Documentation/filesystems/fuse.rst | 6 ++++++
fs/fuse/dir.c | 3 ++-
fs/fuse/fuse_i.h | 4 ++++
fs/fuse/inode.c | 12 +++++++++++-
4 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/Documentation/filesystems/fuse.rst b/Documentation/filesystems/fuse.rst
index 1e31e87aee68..6d3b55476504 100644
--- a/Documentation/filesystems/fuse.rst
+++ b/Documentation/filesystems/fuse.rst
@@ -103,6 +103,12 @@ blksize=N
Set the block size for the filesystem. The default is 512. This
option is only valid for 'fuseblk' type mounts.

+negative_dentry_timeout=N
+ Set the time in seconds to keep negative dentry cache. If a lookup for
+ a path fails, the kernel won't do another lookup for this period of
+ time. The default value is 0, which means that negative dentries are not
+ cached.
+
Control filesystem
==================

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 35bc174f9ba2..21ff395467ab 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -453,7 +453,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
if (outarg_valid)
fuse_change_entry_timeout(entry, &outarg);
else
- fuse_invalidate_entry_cache(entry);
+ fuse_dentry_settime(entry,
+ time_to_jiffies(get_fuse_mount(dir)->negative_dentry_timeout, 0));

if (inode)
fuse_advise_use_readdirplus(dir);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 9b7fc7d3c7f1..bbfe53635329 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -516,6 +516,7 @@ struct fuse_fs_context {
unsigned int max_read;
unsigned int blksize;
const char *subtype;
+ unsigned int negative_dentry_timeout;

/* DAX device, may be NULL */
struct dax_device *dax_dev;
@@ -860,6 +861,9 @@ struct fuse_mount {
*/
struct super_block *sb;

+ /* Timeout on negative denty caches in seconds */
+ u32 negative_dentry_timeout;
+
/* Entry on fc->mounts */
struct list_head fc_entry;
};
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index d66070af145d..45ed0c52f8a6 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -654,7 +654,8 @@ enum {
OPT_ALLOW_OTHER,
OPT_MAX_READ,
OPT_BLKSIZE,
- OPT_ERR
+ OPT_ERR,
+ OPT_NEGATIVE_DENTRY_TIMEOUT
};

static const struct fs_parameter_spec fuse_fs_parameters[] = {
@@ -668,6 +669,7 @@ static const struct fs_parameter_spec fuse_fs_parameters[] = {
fsparam_u32 ("max_read", OPT_MAX_READ),
fsparam_u32 ("blksize", OPT_BLKSIZE),
fsparam_string ("subtype", OPT_SUBTYPE),
+ fsparam_u32 ("negative_dentry_timeout", OPT_NEGATIVE_DENTRY_TIMEOUT),
{}
};

@@ -751,6 +753,10 @@ static int fuse_parse_param(struct fs_context *fsc, struct fs_parameter *param)
ctx->blksize = result.uint_32;
break;

+ case OPT_NEGATIVE_DENTRY_TIMEOUT:
+ ctx->negative_dentry_timeout = result.uint_32;
+ break;
+
default:
return -EINVAL;
}
@@ -1482,6 +1488,10 @@ static int fuse_get_tree_submount(struct fs_context *fsc)
return -ENOMEM;

fm->fc = fuse_conn_get(fc);
+ fm->negative_dentry_timeout =
+ ((struct fuse_fs_context *)fsc->fs_private)
+ ->negative_dentry_timeout;
+
fsc->s_fs_info = fm;
sb = sget_fc(fsc, NULL, set_anon_super_fc);
if (fsc->s_fs_info)
--
2.41.0.185.g7c58973941-goog



2023-06-20 20:04:03

by Miklos Szeredi

[permalink] [raw]
Subject: Re: [PATCH 2/3] fuse: Add negative_dentry_timeout option

On Tue, 20 Jun 2023 at 17:14, Keiichi Watanabe <[email protected]> wrote:
>
> Add `negative_dentry_timeout` mount option for FUSE to cache negative
> dentries for the specified duration.

This is already possible, no kernel changes needed. See e.g.
xmp_init() in libfuse/example/passthrough.c.

Thanks,
Miklos

2023-06-21 04:28:24

by Miklos Szeredi

[permalink] [raw]
Subject: Re: [PATCH 2/3] fuse: Add negative_dentry_timeout option

On Wed, 21 Jun 2023 at 00:53, Junichi Uekawa (上川純一) <[email protected]> wrote:
>
> Hi
>
>
>
> 2023年6月21日(水) 4:28 Miklos Szeredi <[email protected]>:
>>
>> On Tue, 20 Jun 2023 at 17:14, Keiichi Watanabe <[email protected]> wrote:
>> >
>> > Add `negative_dentry_timeout` mount option for FUSE to cache negative
>> > dentries for the specified duration.
>>
>> This is already possible, no kernel changes needed. See e.g.
>> xmp_init() in libfuse/example/passthrough.c.
>>
>
> Thank you for the pointer!
>
> So reading libfuse/fuse.c, fuse_lib_lookup does a reply with e.ino=0 err=0 (instead of ENOENT) with e.entry_timeout=negative_timeout,
> for each lookup (and there's no global configuration but that's okay) ?

Yes.

Thanks,
Miklos

2023-06-21 10:03:29

by Keiichi Watanabe

[permalink] [raw]
Subject: Re: [PATCH 2/3] fuse: Add negative_dentry_timeout option

On Wed, Jun 21, 2023 at 1:07 PM Miklos Szeredi <[email protected]> wrote:
>
> On Wed, 21 Jun 2023 at 00:53, Junichi Uekawa (上川純一) <[email protected]> wrote:
> >
> > Hi
> >
> >
> >
> > 2023年6月21日(水) 4:28 Miklos Szeredi <[email protected]>:
> >>
> >> On Tue, 20 Jun 2023 at 17:14, Keiichi Watanabe <[email protected]> wrote:
> >> >
> >> > Add `negative_dentry_timeout` mount option for FUSE to cache negative
> >> > dentries for the specified duration.
> >>
> >> This is already possible, no kernel changes needed. See e.g.
> >> xmp_init() in libfuse/example/passthrough.c.
> >>
> >
> > Thank you for the pointer!
> >
> > So reading libfuse/fuse.c, fuse_lib_lookup does a reply with e.ino=0 err=0 (instead of ENOENT) with e.entry_timeout=negative_timeout,
> > for each lookup (and there's no global configuration but that's okay) ?
>
> Yes.


Oh, good to know!
I could make it work in our VMM (crosvm) without any kernel changes.
https://crrev.com/c/4630879
Thanks a lot!

Keiichi


>
>
> Thanks,
> Miklos