Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs/9p: Don't open remote file with APPEND mode when writeback cache is used

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>

authored by

Tingmao Wang and committed by
Dominique Martinet
a63dd8fd eeaf38a7

+10 -6
+8 -3
fs/9p/vfs_file.c
··· 43 43 struct v9fs_session_info *v9ses; 44 44 struct p9_fid *fid; 45 45 int omode; 46 + int o_append; 46 47 47 48 p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); 48 49 v9ses = v9fs_inode2v9ses(inode); 49 - if (v9fs_proto_dotl(v9ses)) 50 + if (v9fs_proto_dotl(v9ses)) { 50 51 omode = v9fs_open_to_dotl_flags(file->f_flags); 51 - else 52 + o_append = P9_DOTL_APPEND; 53 + } else { 52 54 omode = v9fs_uflags2omode(file->f_flags, 53 55 v9fs_proto_dotu(v9ses)); 56 + o_append = P9_OAPPEND; 57 + } 54 58 fid = file->private_data; 55 59 if (!fid) { 56 60 fid = v9fs_fid_clone(file_dentry(file)); ··· 62 58 return PTR_ERR(fid); 63 59 64 60 if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) { 65 - int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR; 61 + int writeback_omode = (omode & ~(P9_OWRITE | o_append)) | P9_ORDWR; 66 62 67 63 p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n"); 64 + 68 65 err = p9_client_open(fid, writeback_omode); 69 66 if (err < 0) { 70 67 p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n");
+1 -2
fs/9p/vfs_inode.c
··· 786 786 p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses)); 787 787 788 788 if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { 789 - p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; 789 + p9_omode = (p9_omode & ~(P9_OWRITE | P9_OAPPEND)) | P9_ORDWR; 790 790 p9_debug(P9_DEBUG_CACHE, 791 791 "write-only file with writeback enabled, creating w/ O_RDWR\n"); 792 792 } ··· 1393 1393 .getattr = v9fs_vfs_getattr, 1394 1394 .setattr = v9fs_vfs_setattr, 1395 1395 }; 1396 -
+1 -1
fs/9p/vfs_inode_dotl.c
··· 282 282 } 283 283 284 284 if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { 285 - p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; 285 + p9_omode = (p9_omode & ~(P9_OWRITE | P9_DOTL_APPEND)) | P9_ORDWR; 286 286 p9_debug(P9_DEBUG_CACHE, 287 287 "write-only file with writeback enabled, creating w/ O_RDWR\n"); 288 288 }