aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2019-07-18 18:12:11 -0400
committerSteve French <stfrench@microsoft.com>2019-07-18 18:46:23 -0400
commitaa081859b10c5d8b19f5c525c78883a59d73c2b8 (patch)
treef4cf08099df1b5d188d012dad9c9f61f590e8fcb /fs/cifs
parent89a5bfa350faf87156acda4d7c457808bfecaa0e (diff)
cifs: flush before set-info if we have writeable handles
Servers can defer destaging any data and updating the mtime until close(). This means that if we do a setinfo to modify the mtime while other handles are open for write the server may overwrite our setinfo timestamps when if flushes the file on close() of the writeable handle. To solve this we add an explicit flush when the mtime is about to be updated. This fixes "cp -p" to preserve mtime when copying a file onto an SMB2 share. CC: Stable <stable@vger.kernel.org> Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/inode.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 1bffe029fb66..56ca4b8ccaba 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2406,6 +2406,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
2406 struct inode *inode = d_inode(direntry); 2406 struct inode *inode = d_inode(direntry);
2407 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 2407 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
2408 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 2408 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2409 struct cifsFileInfo *wfile;
2410 struct cifs_tcon *tcon;
2409 char *full_path = NULL; 2411 char *full_path = NULL;
2410 int rc = -EACCES; 2412 int rc = -EACCES;
2411 __u32 dosattr = 0; 2413 __u32 dosattr = 0;
@@ -2452,6 +2454,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
2452 mapping_set_error(inode->i_mapping, rc); 2454 mapping_set_error(inode->i_mapping, rc);
2453 rc = 0; 2455 rc = 0;
2454 2456
2457 if (attrs->ia_valid & ATTR_MTIME) {
2458 rc = cifs_get_writable_file(cifsInode, false, &wfile);
2459 if (!rc) {
2460 tcon = tlink_tcon(wfile->tlink);
2461 rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2462 cifsFileInfo_put(wfile);
2463 if (rc)
2464 return rc;
2465 } else if (rc != -EBADF)
2466 return rc;
2467 else
2468 rc = 0;
2469 }
2470
2455 if (attrs->ia_valid & ATTR_SIZE) { 2471 if (attrs->ia_valid & ATTR_SIZE) {
2456 rc = cifs_set_file_size(inode, attrs, xid, full_path); 2472 rc = cifs_set_file_size(inode, attrs, xid, full_path);
2457 if (rc != 0) 2473 if (rc != 0)