Skip to content

Commit 71e6864

Browse files
committed
smb3: do not error on fsync when readonly
Linux allows doing a flush/fsync on a file open for read-only, but the protocol does not allow that. If the file passed in on the flush is read-only try to find a writeable handle for the same inode, if that is not possible skip sending the fsync call to the server to avoid breaking the apps. Reported-by: Julian Sikorski <[email protected]> Tested-by: Julian Sikorski <[email protected]> Suggested-by: Jeremy Allison <[email protected]> Reviewed-by: Paulo Alcantara (SUSE) <[email protected]> Signed-off-by: Steve French <[email protected]>
1 parent b6f2a0f commit 71e6864

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

fs/cifs/file.c

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,12 +2692,23 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end,
26922692
tcon = tlink_tcon(smbfile->tlink);
26932693
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
26942694
server = tcon->ses->server;
2695-
if (server->ops->flush)
2696-
rc = server->ops->flush(xid, tcon, &smbfile->fid);
2697-
else
2695+
if (server->ops->flush == NULL) {
26982696
rc = -ENOSYS;
2697+
goto strict_fsync_exit;
2698+
}
2699+
2700+
if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
2701+
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
2702+
if (smbfile) {
2703+
rc = server->ops->flush(xid, tcon, &smbfile->fid);
2704+
cifsFileInfo_put(smbfile);
2705+
} else
2706+
cifs_dbg(FYI, "ignore fsync for file not open for write\n");
2707+
} else
2708+
rc = server->ops->flush(xid, tcon, &smbfile->fid);
26992709
}
27002710

2711+
strict_fsync_exit:
27012712
free_xid(xid);
27022713
return rc;
27032714
}
@@ -2709,6 +2720,7 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
27092720
struct cifs_tcon *tcon;
27102721
struct TCP_Server_Info *server;
27112722
struct cifsFileInfo *smbfile = file->private_data;
2723+
struct inode *inode = file_inode(file);
27122724
struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file);
27132725

27142726
rc = file_write_and_wait_range(file, start, end);
@@ -2725,12 +2737,23 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync)
27252737
tcon = tlink_tcon(smbfile->tlink);
27262738
if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) {
27272739
server = tcon->ses->server;
2728-
if (server->ops->flush)
2729-
rc = server->ops->flush(xid, tcon, &smbfile->fid);
2730-
else
2740+
if (server->ops->flush == NULL) {
27312741
rc = -ENOSYS;
2742+
goto fsync_exit;
2743+
}
2744+
2745+
if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) {
2746+
smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY);
2747+
if (smbfile) {
2748+
rc = server->ops->flush(xid, tcon, &smbfile->fid);
2749+
cifsFileInfo_put(smbfile);
2750+
} else
2751+
cifs_dbg(FYI, "ignore fsync for file not open for write\n");
2752+
} else
2753+
rc = server->ops->flush(xid, tcon, &smbfile->fid);
27322754
}
27332755

2756+
fsync_exit:
27342757
free_xid(xid);
27352758
return rc;
27362759
}

0 commit comments

Comments
 (0)