Skip to content

Commit a63dd8f

Browse files
micromaomaomartinetd
authored andcommitted
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: 4eb3117 ("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>
1 parent eeaf38a commit a63dd8f

3 files changed

Lines changed: 10 additions & 6 deletions

File tree

fs/9p/vfs_file.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,29 @@ int v9fs_file_open(struct inode *inode, struct file *file)
4343
struct v9fs_session_info *v9ses;
4444
struct p9_fid *fid;
4545
int omode;
46+
int o_append;
4647

4748
p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file);
4849
v9ses = v9fs_inode2v9ses(inode);
49-
if (v9fs_proto_dotl(v9ses))
50+
if (v9fs_proto_dotl(v9ses)) {
5051
omode = v9fs_open_to_dotl_flags(file->f_flags);
51-
else
52+
o_append = P9_DOTL_APPEND;
53+
} else {
5254
omode = v9fs_uflags2omode(file->f_flags,
5355
v9fs_proto_dotu(v9ses));
56+
o_append = P9_OAPPEND;
57+
}
5458
fid = file->private_data;
5559
if (!fid) {
5660
fid = v9fs_fid_clone(file_dentry(file));
5761
if (IS_ERR(fid))
5862
return PTR_ERR(fid);
5963

6064
if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) {
61-
int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR;
65+
int writeback_omode = (omode & ~(P9_OWRITE | o_append)) | P9_ORDWR;
6266

6367
p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n");
68+
6469
err = p9_client_open(fid, writeback_omode);
6570
if (err < 0) {
6671
p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n");

fs/9p/vfs_inode.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
786786
p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses));
787787

788788
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;
790790
p9_debug(P9_DEBUG_CACHE,
791791
"write-only file with writeback enabled, creating w/ O_RDWR\n");
792792
}
@@ -1393,4 +1393,3 @@ static const struct inode_operations v9fs_symlink_inode_operations = {
13931393
.getattr = v9fs_vfs_getattr,
13941394
.setattr = v9fs_vfs_setattr,
13951395
};
1396-

fs/9p/vfs_inode_dotl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
282282
}
283283

284284
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;
286286
p9_debug(P9_DEBUG_CACHE,
287287
"write-only file with writeback enabled, creating w/ O_RDWR\n");
288288
}

0 commit comments

Comments
 (0)