]> www.infradead.org Git - users/hch/misc.git/commitdiff
Revert "fs/9p: Refresh metadata in d_revalidate for uncached mode too"
authorDominique Martinet <asmadeus@codewreck.org>
Tue, 21 Oct 2025 21:33:42 +0000 (06:33 +0900)
committerDominique Martinet <asmadeus@codewreck.org>
Wed, 22 Oct 2025 05:25:27 +0000 (14:25 +0900)
This reverts commit 290434474c332a2ba9c8499fe699c7f2e1153280.

That commit broke cache=mmap, a mode that doesn't cache metadata,
but still has writeback cache.

In commit 290434474c33 ("fs/9p: Refresh metadata in d_revalidate
for uncached mode too") we considered metadata cache to be enough to
not look at the server, but in writeback cache too looking at the server
size would make the vfs consider the file has been truncated before the
data has been flushed out, making the following repro fail (nothing is
ever read back, the resulting file ends up with no data written)
```
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

char buf[4096];

int main(int argc, char *argv[])
{
        int ret, i;
        int fdw, fdr;

        if (argc < 2)
                return 1;

        fdw = openat(AT_FDCWD, argv[1], O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0600);
        if (fdw < 0) {
                fprintf(stderr, "cannot open fdw\n");
                return 1;
        }
        write(fdw, buf, sizeof(buf));

        fdr = openat(AT_FDCWD, argv[1], O_RDONLY|O_CLOEXEC);

        if (fdr < 0) {
                fprintf(stderr, "cannot open fdr\n");
                close(fdw);
                return 1;
        }

        for (i = 0; i < 10; i++) {
                ret = read(fdr, buf, sizeof(buf));
                fprintf(stderr, "i: %d, read returns %d\n", i, ret);
        }

        close(fdr);
        close(fdw);
        return 0;
}
```

There is a fix for this particular reproducer but it looks like there
are other problems around metadata refresh (e.g. around file rename), so
revert this to avoid d_revalidate in uncached mode for now.

Reported-by: Song Liu <song@kernel.org>
Link: https://lkml.kernel.org/r/CAHzjS_u_SYdt5=2gYO_dxzMKXzGMt-TfdE_ueowg-Hq5tRCAiw@mail.gmail.com
Reported-by: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Link: https://lore.kernel.org/bpf/CAEf4BzZbCE4tLoDZyUf_aASpgAGFj75QMfSXX4a4dLYixnOiLg@mail.gmail.com/
Fixes: 290434474c33 ("fs/9p: Refresh metadata in d_revalidate for uncached mode too")
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
fs/9p/vfs_dentry.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c

index f3248a3e54023489054337bf98e87a1d7b1fbafc..c1acbc98465deb8f14f3d76fe1d51785855f5b5b 100644 (file)
@@ -66,7 +66,6 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
        struct p9_fid *fid;
        struct inode *inode;
        struct v9fs_inode *v9inode;
-       unsigned int cached;
 
        if (flags & LOOKUP_RCU)
                return -ECHILD;
@@ -76,11 +75,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
                goto out_valid;
 
        v9inode = V9FS_I(inode);
-       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
-
-       cached = v9ses->cache & (CACHE_META | CACHE_LOOSE);
-
-       if (!cached || v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
+       if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) {
                int retval;
                struct v9fs_session_info *v9ses;
 
@@ -114,6 +109,7 @@ static int __v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
                        p9_debug(P9_DEBUG_VFS,
                                "refresh inode: dentry = %pd (%p), got error %pe\n",
                                dentry, dentry, ERR_PTR(retval));
+               if (retval < 0)
                        return retval;
                }
        }
@@ -150,8 +146,6 @@ const struct dentry_operations v9fs_cached_dentry_operations = {
 };
 
 const struct dentry_operations v9fs_dentry_operations = {
-       .d_revalidate = v9fs_lookup_revalidate,
-       .d_weak_revalidate = __v9fs_lookup_revalidate,
        .d_release = v9fs_dentry_release,
        .d_unalias_trylock = v9fs_dentry_unalias_trylock,
        .d_unalias_unlock = v9fs_dentry_unalias_unlock,
index 69f378a837753e934c20b599660f8a756127e40a..d0c77ec31b1dd66416c78d285d9ed91802d9cf42 100644 (file)
@@ -1339,14 +1339,8 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode)
         * Don't update inode if the file type is different
         */
        umode = p9mode2unixmode(v9ses, st, &rdev);
-       if (inode_wrong_type(inode, umode)) {
-               /*
-                * Do this as a way of letting the caller know the inode should not
-                * be reused
-                */
-               v9fs_invalidate_inode_attr(inode);
+       if (inode_wrong_type(inode, umode))
                goto out;
-       }
 
        /*
         * We don't want to refresh inode->i_size,
index 0b404e8484d22e2cbe60d846e0fa653001cdc4b1..be297e33546889d99531562431af47cb0f1b1fe6 100644 (file)
@@ -897,14 +897,8 @@ int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
        /*
         * Don't update inode if the file type is different
         */
-       if (inode_wrong_type(inode, st->st_mode)) {
-               /*
-                * Do this as a way of letting the caller know the inode should not
-                * be reused
-                */
-               v9fs_invalidate_inode_attr(inode);
+       if (inode_wrong_type(inode, st->st_mode))
                goto out;
-       }
 
        /*
         * We don't want to refresh inode->i_size,