| From b97935b58cd8d6a260b97c42ba221f1f0379b248 Mon Sep 17 00:00:00 2001 |
| From: Steve French <stfrench@microsoft.com> |
| Date: Mon, 24 Feb 2020 17:37:39 -0600 |
| Subject: [PATCH] smb3: fix performance regression with setting mtime |
| |
| commit cf5371ae460eb8e484e4884747af270c86c3c469 upstream. |
| |
| There are cases when we don't want to send the SMB2 flush operation |
| (e.g. when user specifies mount parm "nostrictsync") and it can be |
| a very expensive operation on the server. In most cases in order |
| to set mtime, we simply need to flush (write) the dirtry pages from |
| the client and send the writes to the server not also send a flush |
| protocol operation to the server. |
| |
| Fixes: aa081859b10c ("cifs: flush before set-info if we have writeable handles") |
| CC: Stable <stable@vger.kernel.org> |
| Signed-off-by: Steve French <stfrench@microsoft.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c |
| index 6e974a90e491..3d77ffc6c1b7 100644 |
| --- a/fs/cifs/inode.c |
| +++ b/fs/cifs/inode.c |
| @@ -2442,25 +2442,26 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) |
| |
| /* |
| * Attempt to flush data before changing attributes. We need to do |
| - * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the |
| - * ownership or mode then we may also need to do this. Here, we take |
| - * the safe way out and just do the flush on all setattr requests. If |
| - * the flush returns error, store it to report later and continue. |
| + * this for ATTR_SIZE and ATTR_MTIME. If the flush of the data |
| + * returns error, store it to report later and continue. |
| * |
| * BB: This should be smarter. Why bother flushing pages that |
| * will be truncated anyway? Also, should we error out here if |
| - * the flush returns error? |
| + * the flush returns error? Do we need to check for ATTR_MTIME_SET flag? |
| */ |
| - rc = filemap_write_and_wait(inode->i_mapping); |
| - if (is_interrupt_error(rc)) { |
| - rc = -ERESTARTSYS; |
| - goto cifs_setattr_exit; |
| + if (attrs->ia_valid & (ATTR_MTIME | ATTR_SIZE | ATTR_CTIME)) { |
| + rc = filemap_write_and_wait(inode->i_mapping); |
| + if (is_interrupt_error(rc)) { |
| + rc = -ERESTARTSYS; |
| + goto cifs_setattr_exit; |
| + } |
| + mapping_set_error(inode->i_mapping, rc); |
| } |
| |
| - mapping_set_error(inode->i_mapping, rc); |
| rc = 0; |
| |
| - if (attrs->ia_valid & ATTR_MTIME) { |
| + if ((attrs->ia_valid & ATTR_MTIME) && |
| + !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { |
| rc = cifs_get_writable_file(cifsInode, false, &wfile); |
| if (!rc) { |
| tcon = tlink_tcon(wfile->tlink); |
| -- |
| 2.7.4 |
| |