* Re: [PATCH] fuse: invalidate readdir cache on epoch bump
2026-03-31 22:39 [PATCH] fuse: invalidate readdir cache on epoch bump Jun Wu
@ 2026-05-12 19:58 ` Joanne Koong
2026-05-14 23:09 ` [PATCH v2] " Jun Wu
2026-05-15 0:14 ` Jun Wu
2 siblings, 0 replies; 8+ messages in thread
From: Joanne Koong @ 2026-05-12 19:58 UTC (permalink / raw)
To: Jun Wu; +Cc: miklos, linux-fsdevel, Jun Wu, fuse-devel
On Tue, Mar 31, 2026 at 3:40 PM Jun Wu <quark@lihdd.net> wrote:
>
> From: Jun Wu <quark@meta.com>
>
> FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
> readdir results. A process with cwd inside a FUSE mount can therefore
> observe stale readdir(".") output after an epoch bump.
>
> Fix this by recording epoch in the readdir cache and checking it on reuse.
>
> Add FUSE_EPOCH_READDIR init flag so userspace can detect this change.
imo this is more of a fix than a new feature, so I don't think the
changes for adding the FUSE_EPOCH_READDIR init flag is necessary. I
think the Fixes: 2396356a945b ("fuse: add more control over cache
invalidation behaviour") tag fits here.
Other than that, this change makes sense to me.
Thanks,
Joanne
>
> Minimal reproducer:
>
> - mount a tiny FUSE fs with an empty root directory
> - on opendir, enable fi->cache_readdir and fi->keep_cache
> - chdir into the mount and call readdir(".") to populate readdir cache
> - make the FUSE server report one file in the root directory
> - send only FUSE_NOTIFY_INC_EPOCH
> - call readdir(".") again; before this change it stays stale, after this
> change it sees the new file
>
> Signed-off-by: Jun Wu <quark@meta.com>
> ---
> fs/fuse/dev.c | 6 +++---
> fs/fuse/fuse_i.h | 3 +++
> fs/fuse/inode.c | 2 +-
> fs/fuse/readdir.c | 5 ++++-
> include/uapi/linux/fuse.h | 3 +++
> 5 files changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 0b0241f47170..595f90f44772 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -2039,9 +2039,9 @@ static int fuse_notify_resend(struct fuse_conn *fc)
> }
>
> /*
> - * Increments the fuse connection epoch. This will result of dentries from
> - * previous epochs to be invalidated. Additionally, if inval_wq is set, a work
> - * queue is scheduled to trigger the invalidation.
> + * Increments the fuse connection epoch. This will cause dentries and
> + * readdir caches from previous epochs to be invalidated. Additionally,
> + * if inval_wq is set, a work queue is scheduled to trigger the invalidation.
> */
> static int fuse_notify_inc_epoch(struct fuse_conn *fc)
> {
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 7f16049387d1..9b479f597938 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -191,6 +191,9 @@ struct fuse_inode {
> /* iversion of directory when cache was started */
> u64 iversion;
>
> + /* epoch of fc when cache was started */
> + int epoch;
> +
> /* protects above fields */
> spinlock_t lock;
> } rdc;
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index c795abe47a4f..5685e696ee2f 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -1506,7 +1506,7 @@ static struct fuse_init_args *fuse_new_init(struct fuse_mount *fm)
> FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
> FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP |
> FUSE_NO_EXPORT_SUPPORT | FUSE_HAS_RESEND | FUSE_ALLOW_IDMAP |
> - FUSE_REQUEST_TIMEOUT;
> + FUSE_REQUEST_TIMEOUT | FUSE_EPOCH_READDIR;
> #ifdef CONFIG_FUSE_DAX
> if (fm->fc->dax)
> flags |= FUSE_MAP_ALIGNMENT;
> diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
> index c2aae2eef086..240b0e993780 100644
> --- a/fs/fuse/readdir.c
> +++ b/fs/fuse/readdir.c
> @@ -438,6 +438,7 @@ static void fuse_rdc_reset(struct inode *inode)
> fi->rdc.version++;
> fi->rdc.size = 0;
> fi->rdc.pos = 0;
> + fi->rdc.epoch = 0;
> }
>
> #define UNCACHED 1
> @@ -479,6 +480,7 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
> if (!ctx->pos && !fi->rdc.size) {
> fi->rdc.mtime = inode_get_mtime(inode);
> fi->rdc.iversion = inode_query_iversion(inode);
> + fi->rdc.epoch = atomic_read(&fc->epoch);
> }
> spin_unlock(&fi->rdc.lock);
> return UNCACHED;
> @@ -492,7 +494,8 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
> struct timespec64 mtime = inode_get_mtime(inode);
>
> if (inode_peek_iversion(inode) != fi->rdc.iversion ||
> - !timespec64_equal(&fi->rdc.mtime, &mtime)) {
> + !timespec64_equal(&fi->rdc.mtime, &mtime) ||
> + fi->rdc.epoch != atomic_read(&fc->epoch)) {
> fuse_rdc_reset(inode);
> goto retry_locked;
> }
> diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
> index c13e1f9a2f12..b0bd96ac1e84 100644
> --- a/include/uapi/linux/fuse.h
> +++ b/include/uapi/linux/fuse.h
> @@ -240,6 +240,7 @@
> * - add FUSE_COPY_FILE_RANGE_64
> * - add struct fuse_copy_file_range_out
> * - add FUSE_NOTIFY_PRUNE
> + * - add FUSE_EPOCH_READDIR
> */
>
> #ifndef _LINUX_FUSE_H
> @@ -448,6 +449,7 @@ struct fuse_file_lock {
> * FUSE_OVER_IO_URING: Indicate that client supports io-uring
> * FUSE_REQUEST_TIMEOUT: kernel supports timing out requests.
> * init_out.request_timeout contains the timeout (in secs)
> + * FUSE_EPOCH_READDIR: epoch bump also invalidates readdir caches
> */
> #define FUSE_ASYNC_READ (1 << 0)
> #define FUSE_POSIX_LOCKS (1 << 1)
> @@ -495,6 +497,7 @@ struct fuse_file_lock {
> #define FUSE_ALLOW_IDMAP (1ULL << 40)
> #define FUSE_OVER_IO_URING (1ULL << 41)
> #define FUSE_REQUEST_TIMEOUT (1ULL << 42)
> +#define FUSE_EPOCH_READDIR (1ULL << 43)
>
> /**
> * CUSE INIT request/reply flags
> --
> 2.53.0
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2] fuse: invalidate readdir cache on epoch bump
2026-03-31 22:39 [PATCH] fuse: invalidate readdir cache on epoch bump Jun Wu
2026-05-12 19:58 ` Joanne Koong
@ 2026-05-14 23:09 ` Jun Wu
2026-05-15 0:14 ` Jun Wu
2 siblings, 0 replies; 8+ messages in thread
From: Jun Wu @ 2026-05-14 23:09 UTC (permalink / raw)
To: miklos; +Cc: luis, linux-fsdevel, fuse-devel, Jun Wu
From: Jun Wu <quark@meta.com>
FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
readdir results. A process with cwd inside a FUSE mount can therefore
observe stale readdir(".") output after an epoch bump.
Fix this by recording epoch in the readdir cache and checking it on reuse.
Minimal reproducer:
- mount a tiny FUSE fs with an empty root directory
- on opendir, enable fi->cache_readdir and fi->keep_cache
- chdir into the mount and call readdir(".") to populate readdir cache
- make the FUSE server report one file in the root directory
- send only FUSE_NOTIFY_INC_EPOCH
- call readdir(".") again; before this change it stays stale, after this
change it sees the new file
Fixes: 2396356a945b ("fuse: add more control over cache invalidation behaviour")
Signed-off-by: Jun Wu <quark@meta.com>
---
Changes in v2:
- Addresses Joanne Koong's suggestions:
- Drop the FUSE_EPOCH_READDIR init flag.
- Add Fixes tag.
- Rebase onto current mainline.
---
fs/fuse/dev.c | 6 +++---
fs/fuse/fuse_i.h | 3 +++
fs/fuse/readdir.c | 5 ++++-
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5dda7080f4a9..35e04b064f37 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2038,9 +2038,9 @@ static int fuse_notify_resend(struct fuse_conn *fc)
}
/*
- * Increments the fuse connection epoch. This will result of dentries from
- * previous epochs to be invalidated. Additionally, if inval_wq is set, a work
- * queue is scheduled to trigger the invalidation.
+ * Increments the fuse connection epoch. This will cause dentries and
+ * readdir caches from previous epochs to be invalidated. Additionally,
+ * if inval_wq is set, a work queue is scheduled to trigger the invalidation.
*/
static int fuse_notify_inc_epoch(struct fuse_conn *fc)
{
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 17423d4e3cfa..aa8d6dfbbcc7 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -191,6 +191,9 @@ struct fuse_inode {
/* iversion of directory when cache was started */
u64 iversion;
+ /* epoch of fc when cache was started */
+ int epoch;
+
/* protects above fields */
spinlock_t lock;
} rdc;
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index db5ae8ec1030..b18d971e2bb4 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -442,6 +442,7 @@ static void fuse_rdc_reset(struct inode *inode)
fi->rdc.version++;
fi->rdc.size = 0;
fi->rdc.pos = 0;
+ fi->rdc.epoch = 0;
}
#define UNCACHED 1
@@ -483,6 +484,7 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
if (!ctx->pos && !fi->rdc.size) {
fi->rdc.mtime = inode_get_mtime(inode);
fi->rdc.iversion = inode_query_iversion(inode);
+ fi->rdc.epoch = atomic_read(&fc->epoch);
}
spin_unlock(&fi->rdc.lock);
return UNCACHED;
@@ -496,7 +498,8 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
struct timespec64 mtime = inode_get_mtime(inode);
if (inode_peek_iversion(inode) != fi->rdc.iversion ||
- !timespec64_equal(&fi->rdc.mtime, &mtime)) {
+ !timespec64_equal(&fi->rdc.mtime, &mtime) ||
+ fi->rdc.epoch != atomic_read(&fc->epoch)) {
fuse_rdc_reset(inode);
goto retry_locked;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH v2] fuse: invalidate readdir cache on epoch bump
2026-03-31 22:39 [PATCH] fuse: invalidate readdir cache on epoch bump Jun Wu
2026-05-12 19:58 ` Joanne Koong
2026-05-14 23:09 ` [PATCH v2] " Jun Wu
@ 2026-05-15 0:14 ` Jun Wu
2026-05-15 8:53 ` Luis Henriques
2 siblings, 1 reply; 8+ messages in thread
From: Jun Wu @ 2026-05-15 0:14 UTC (permalink / raw)
To: fuse-devel; +Cc: miklos, luis, Jun Wu
From: Jun Wu <quark@meta.com>
FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
readdir results. A process with cwd inside a FUSE mount can therefore
observe stale readdir(".") output after an epoch bump.
Fix this by recording epoch in the readdir cache and checking it on reuse.
Minimal reproducer:
- mount a tiny FUSE fs with an empty root directory
- on opendir, enable fi->cache_readdir and fi->keep_cache
- chdir into the mount and call readdir(".") to populate readdir cache
- make the FUSE server report one file in the root directory
- send only FUSE_NOTIFY_INC_EPOCH
- call readdir(".") again; before this change it stays stale, after this
change it sees the new file
Fixes: 2396356a945b ("fuse: add more control over cache invalidation behaviour")
Signed-off-by: Jun Wu <quark@meta.com>
---
Changes in v2:
- Addresses Joanne Koong's suggestions:
- Drop the FUSE_EPOCH_READDIR init flag.
- Add Fixes tag.
- Rebase onto current mainline.
---
fs/fuse/dev.c | 6 +++---
fs/fuse/fuse_i.h | 3 +++
fs/fuse/readdir.c | 5 ++++-
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5dda7080f4a9..35e04b064f37 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2038,9 +2038,9 @@ static int fuse_notify_resend(struct fuse_conn *fc)
}
/*
- * Increments the fuse connection epoch. This will result of dentries from
- * previous epochs to be invalidated. Additionally, if inval_wq is set, a work
- * queue is scheduled to trigger the invalidation.
+ * Increments the fuse connection epoch. This will cause dentries and
+ * readdir caches from previous epochs to be invalidated. Additionally,
+ * if inval_wq is set, a work queue is scheduled to trigger the invalidation.
*/
static int fuse_notify_inc_epoch(struct fuse_conn *fc)
{
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 17423d4e3cfa..aa8d6dfbbcc7 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -191,6 +191,9 @@ struct fuse_inode {
/* iversion of directory when cache was started */
u64 iversion;
+ /* epoch of fc when cache was started */
+ int epoch;
+
/* protects above fields */
spinlock_t lock;
} rdc;
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index db5ae8ec1030..b18d971e2bb4 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -442,6 +442,7 @@ static void fuse_rdc_reset(struct inode *inode)
fi->rdc.version++;
fi->rdc.size = 0;
fi->rdc.pos = 0;
+ fi->rdc.epoch = 0;
}
#define UNCACHED 1
@@ -483,6 +484,7 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
if (!ctx->pos && !fi->rdc.size) {
fi->rdc.mtime = inode_get_mtime(inode);
fi->rdc.iversion = inode_query_iversion(inode);
+ fi->rdc.epoch = atomic_read(&fc->epoch);
}
spin_unlock(&fi->rdc.lock);
return UNCACHED;
@@ -496,7 +498,8 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
struct timespec64 mtime = inode_get_mtime(inode);
if (inode_peek_iversion(inode) != fi->rdc.iversion ||
- !timespec64_equal(&fi->rdc.mtime, &mtime)) {
+ !timespec64_equal(&fi->rdc.mtime, &mtime) ||
+ fi->rdc.epoch != atomic_read(&fc->epoch)) {
fuse_rdc_reset(inode);
goto retry_locked;
}
--
2.54.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v2] fuse: invalidate readdir cache on epoch bump
2026-05-15 0:14 ` Jun Wu
@ 2026-05-15 8:53 ` Luis Henriques
2026-05-15 15:36 ` Joanne Koong
0 siblings, 1 reply; 8+ messages in thread
From: Luis Henriques @ 2026-05-15 8:53 UTC (permalink / raw)
To: Jun Wu; +Cc: fuse-devel, miklos, Jun Wu
On Thu, May 14 2026, Jun Wu wrote:
> From: Jun Wu <quark@meta.com>
>
> FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
> readdir results. A process with cwd inside a FUSE mount can therefore
> observe stale readdir(".") output after an epoch bump.
>
> Fix this by recording epoch in the readdir cache and checking it on reuse.
>
> Minimal reproducer:
>
> - mount a tiny FUSE fs with an empty root directory
> - on opendir, enable fi->cache_readdir and fi->keep_cache
> - chdir into the mount and call readdir(".") to populate readdir cache
> - make the FUSE server report one file in the root directory
> - send only FUSE_NOTIFY_INC_EPOCH
> - call readdir(".") again; before this change it stays stale, after this
> change it sees the new file
>
> Fixes: 2396356a945b ("fuse: add more control over cache invalidation behaviour")
> Signed-off-by: Jun Wu <quark@meta.com>
Nice catch! The fix looks good to me, so feel free to add my
Reviewed-by: Luis Henriques <luis@igalia.com>
Cheers,
--
Luís
> ---
> Changes in v2:
> - Addresses Joanne Koong's suggestions:
> - Drop the FUSE_EPOCH_READDIR init flag.
> - Add Fixes tag.
> - Rebase onto current mainline.
> ---
> fs/fuse/dev.c | 6 +++---
> fs/fuse/fuse_i.h | 3 +++
> fs/fuse/readdir.c | 5 ++++-
> 3 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 5dda7080f4a9..35e04b064f37 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -2038,9 +2038,9 @@ static int fuse_notify_resend(struct fuse_conn *fc)
> }
>
> /*
> - * Increments the fuse connection epoch. This will result of dentries from
> - * previous epochs to be invalidated. Additionally, if inval_wq is set, a work
> - * queue is scheduled to trigger the invalidation.
> + * Increments the fuse connection epoch. This will cause dentries and
> + * readdir caches from previous epochs to be invalidated. Additionally,
> + * if inval_wq is set, a work queue is scheduled to trigger the invalidation.
> */
> static int fuse_notify_inc_epoch(struct fuse_conn *fc)
> {
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index 17423d4e3cfa..aa8d6dfbbcc7 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -191,6 +191,9 @@ struct fuse_inode {
> /* iversion of directory when cache was started */
> u64 iversion;
>
> + /* epoch of fc when cache was started */
> + int epoch;
> +
> /* protects above fields */
> spinlock_t lock;
> } rdc;
> diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
> index db5ae8ec1030..b18d971e2bb4 100644
> --- a/fs/fuse/readdir.c
> +++ b/fs/fuse/readdir.c
> @@ -442,6 +442,7 @@ static void fuse_rdc_reset(struct inode *inode)
> fi->rdc.version++;
> fi->rdc.size = 0;
> fi->rdc.pos = 0;
> + fi->rdc.epoch = 0;
> }
>
> #define UNCACHED 1
> @@ -483,6 +484,7 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
> if (!ctx->pos && !fi->rdc.size) {
> fi->rdc.mtime = inode_get_mtime(inode);
> fi->rdc.iversion = inode_query_iversion(inode);
> + fi->rdc.epoch = atomic_read(&fc->epoch);
> }
> spin_unlock(&fi->rdc.lock);
> return UNCACHED;
> @@ -496,7 +498,8 @@ static int fuse_readdir_cached(struct file *file, struct dir_context *ctx)
> struct timespec64 mtime = inode_get_mtime(inode);
>
> if (inode_peek_iversion(inode) != fi->rdc.iversion ||
> - !timespec64_equal(&fi->rdc.mtime, &mtime)) {
> + !timespec64_equal(&fi->rdc.mtime, &mtime) ||
> + fi->rdc.epoch != atomic_read(&fc->epoch)) {
> fuse_rdc_reset(inode);
> goto retry_locked;
> }
> --
> 2.54.0
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v2] fuse: invalidate readdir cache on epoch bump
2026-05-15 8:53 ` Luis Henriques
@ 2026-05-15 15:36 ` Joanne Koong
2026-05-15 16:26 ` Luis Henriques
0 siblings, 1 reply; 8+ messages in thread
From: Joanne Koong @ 2026-05-15 15:36 UTC (permalink / raw)
To: Luis Henriques; +Cc: Jun Wu, fuse-devel, miklos, Jun Wu
On Fri, May 15, 2026 at 1:53 AM Luis Henriques <luis@igalia.com> wrote:
>
> On Thu, May 14 2026, Jun Wu wrote:
>
> > From: Jun Wu <quark@meta.com>
> >
> > FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
> > readdir results. A process with cwd inside a FUSE mount can therefore
> > observe stale readdir(".") output after an epoch bump.
> >
> > Fix this by recording epoch in the readdir cache and checking it on reuse.
> >
> > Minimal reproducer:
> >
> > - mount a tiny FUSE fs with an empty root directory
> > - on opendir, enable fi->cache_readdir and fi->keep_cache
> > - chdir into the mount and call readdir(".") to populate readdir cache
> > - make the FUSE server report one file in the root directory
> > - send only FUSE_NOTIFY_INC_EPOCH
> > - call readdir(".") again; before this change it stays stale, after this
> > change it sees the new file
> >
> > Fixes: 2396356a945b ("fuse: add more control over cache invalidation behaviour")
> > Signed-off-by: Jun Wu <quark@meta.com>
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
(btw, I think your v2 email may have gotten corrupted when sending. I
wasn't able to find it in my inbox and had to manually import Luis's.
I'm not seeing it show up on lore [1] either)
Thanks,
Joanne
[1] https://lore.kernel.org/fuse-devel/CAJnrk1YOzwNRS+qA74rLMFmx=JgE3VVueu9o7-pghsa4bPzYBw@mail.gmail.com/T/#t
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v2] fuse: invalidate readdir cache on epoch bump
2026-05-15 15:36 ` Joanne Koong
@ 2026-05-15 16:26 ` Luis Henriques
[not found] ` <CAFfKmRW_Dqtb_DwAgK5Oq5kTAnGY6bmRpYP-Gw2+PVBtU4YVtQ@mail.gmail.com>
0 siblings, 1 reply; 8+ messages in thread
From: Luis Henriques @ 2026-05-15 16:26 UTC (permalink / raw)
To: Joanne Koong; +Cc: Jun Wu, fuse-devel, miklos, Jun Wu
On Fri, May 15 2026, Joanne Koong wrote:
> On Fri, May 15, 2026 at 1:53 AM Luis Henriques <luis@igalia.com> wrote:
>>
>> On Thu, May 14 2026, Jun Wu wrote:
>>
>> > From: Jun Wu <quark@meta.com>
>> >
>> > FUSE_NOTIFY_INC_EPOCH invalidates dentries, but does not invalidate cached
>> > readdir results. A process with cwd inside a FUSE mount can therefore
>> > observe stale readdir(".") output after an epoch bump.
>> >
>> > Fix this by recording epoch in the readdir cache and checking it on reuse.
>> >
>> > Minimal reproducer:
>> >
>> > - mount a tiny FUSE fs with an empty root directory
>> > - on opendir, enable fi->cache_readdir and fi->keep_cache
>> > - chdir into the mount and call readdir(".") to populate readdir cache
>> > - make the FUSE server report one file in the root directory
>> > - send only FUSE_NOTIFY_INC_EPOCH
>> > - call readdir(".") again; before this change it stays stale, after this
>> > change it sees the new file
>> >
>> > Fixes: 2396356a945b ("fuse: add more control over cache invalidation behaviour")
>> > Signed-off-by: Jun Wu <quark@meta.com>
>
> Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
>
> (btw, I think your v2 email may have gotten corrupted when sending. I
> wasn't able to find it in my inbox and had to manually import Luis's.
> I'm not seeing it show up on lore [1] either)
Hmm... yeah, looks like there's something funny with his email. The mail
server I use seems to be more tolerant than lore regarding incorrect
email. So maybe lore blocked it because the domain and the smtp server
address don't match...? Anyway, maybe it's worth resending so that
everyone can see it.
Cheers,
--
Luís
^ permalink raw reply [flat|nested] 8+ messages in thread