]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
fs/9p: Don't open remote file with APPEND mode when writeback cache is used
authorTingmao Wang <m@maowtm.org>
Sun, 2 Nov 2025 23:56:30 +0000 (23:56 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 12:54:53 +0000 (13:54 +0100)
[ Upstream commit a63dd8fd137933551bfd9aeeeaa942f04c7aad65 ]

When page cache is used, writebacks are done on a page granularity, and it
is expected that the underlying filesystem (such as v9fs) should respect
the write position.  However, currently v9fs will passthrough O_APPEND to
the server even on cached mode.  This causes data corruption if a sync or
fstat gets between two writes to the same file.

This patch removes the APPEND flag from the open request we send to the
server when writeback caching is involved.  I believe keeping server-side
APPEND is probably fine for uncached mode (even if two fds are opened, one
without O_APPEND and one with it, this should still be fine since they
would use separate fid for the writes).

Signed-off-by: Tingmao Wang <m@maowtm.org>
Fixes: 4eb3117888a9 ("fs/9p: Rework cache modes and add new options to Documentation")
Message-ID: <20251102235631.8724-1-m@maowtm.org>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c

index 348cc90bf9c56b7184dbac73faffe8d5f3d2762e..de0d1f74de46c0cda1b0feeb0bf2fe08614680e5 100644 (file)
@@ -43,14 +43,18 @@ int v9fs_file_open(struct inode *inode, struct file *file)
        struct v9fs_session_info *v9ses;
        struct p9_fid *fid;
        int omode;
+       int o_append;
 
        p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file);
        v9ses = v9fs_inode2v9ses(inode);
-       if (v9fs_proto_dotl(v9ses))
+       if (v9fs_proto_dotl(v9ses)) {
                omode = v9fs_open_to_dotl_flags(file->f_flags);
-       else
+               o_append = P9_DOTL_APPEND;
+       } else {
                omode = v9fs_uflags2omode(file->f_flags,
                                        v9fs_proto_dotu(v9ses));
+               o_append = P9_OAPPEND;
+       }
        fid = file->private_data;
        if (!fid) {
                fid = v9fs_fid_clone(file_dentry(file));
@@ -58,9 +62,10 @@ int v9fs_file_open(struct inode *inode, struct file *file)
                        return PTR_ERR(fid);
 
                if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) {
-                       int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR;
+                       int writeback_omode = (omode & ~(P9_OWRITE | o_append)) | P9_ORDWR;
 
                        p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n");
+
                        err = p9_client_open(fid, writeback_omode);
                        if (err < 0) {
                                p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n");
index 3e68521f4e2f9842019cdea2755d8a657a8ebb21..1723a37d1846e05b621d8ab6d1723ef750b16855 100644 (file)
@@ -791,7 +791,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
        p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses));
 
        if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) {
-               p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR;
+               p9_omode = (p9_omode & ~(P9_OWRITE | P9_OAPPEND)) | P9_ORDWR;
                p9_debug(P9_DEBUG_CACHE,
                        "write-only file with writeback enabled, creating w/ O_RDWR\n");
        }
@@ -1404,4 +1404,3 @@ static const struct inode_operations v9fs_symlink_inode_operations = {
        .getattr = v9fs_vfs_getattr,
        .setattr = v9fs_vfs_setattr,
 };
-
index 3397939fd2d5affb0e9082444d5c2580c10e7788..40a4fc65a54415bfba05e4f6159fcf02d5c9ea5b 100644 (file)
@@ -286,7 +286,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        }
 
        if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) {
-               p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR;
+               p9_omode = (p9_omode & ~(P9_OWRITE | P9_DOTL_APPEND)) | P9_ORDWR;
                p9_debug(P9_DEBUG_CACHE,
                        "write-only file with writeback enabled, creating w/ O_RDWR\n");
        }