aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-03-26 13:35:37 -0400
committerSteve French <sfrench@us.ibm.com>2009-04-16 21:26:48 -0400
commit0f4d634c59a4e062bef81c00d9e63333f2a83b46 (patch)
treeb71dbcddf45eee405ea9bb615ef621b9a09a9994 /fs/cifs/inode.c
parent20d9207849d5abe60461841b3c3724f6e7c9d33e (diff)
cifs: flush data on any setattr
We already flush all the dirty pages for an inode before doing ATTR_SIZE and ATTR_MTIME changes. There's another problem though -- if we change the mode so that the file becomes read-only then we may not be able to write data to it after a reconnect. Fix this by just going back to flushing all the dirty data on any setattr call. There are probably some cases that can be optimized out, but I'm not sure they're worthwhile and we need to consider them more carefully to make sure that we don't cause regressions if we have to reconnect before writeback occurs. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c58
1 files changed, 30 insertions, 28 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index f121a80fdd6f..89063f1eb55b 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -1792,20 +1792,21 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
1792 goto out; 1792 goto out;
1793 } 1793 }
1794 1794
1795 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1795 /*
1796 /* 1796 * Attempt to flush data before changing attributes. We need to do
1797 Flush data before changing file size or changing the last 1797 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1798 write time of the file on the server. If the 1798 * ownership or mode then we may also need to do this. Here, we take
1799 flush returns error, store it to report later and continue. 1799 * the safe way out and just do the flush on all setattr requests. If
1800 BB: This should be smarter. Why bother flushing pages that 1800 * the flush returns error, store it to report later and continue.
1801 will be truncated anyway? Also, should we error out here if 1801 *
1802 the flush returns error? 1802 * BB: This should be smarter. Why bother flushing pages that
1803 */ 1803 * will be truncated anyway? Also, should we error out here if
1804 rc = filemap_write_and_wait(inode->i_mapping); 1804 * the flush returns error?
1805 if (rc != 0) { 1805 */
1806 cifsInode->write_behind_rc = rc; 1806 rc = filemap_write_and_wait(inode->i_mapping);
1807 rc = 0; 1807 if (rc != 0) {
1808 } 1808 cifsInode->write_behind_rc = rc;
1809 rc = 0;
1809 } 1810 }
1810 1811
1811 if (attrs->ia_valid & ATTR_SIZE) { 1812 if (attrs->ia_valid & ATTR_SIZE) {
@@ -1903,20 +1904,21 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
1903 return -ENOMEM; 1904 return -ENOMEM;
1904 } 1905 }
1905 1906
1906 if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { 1907 /*
1907 /* 1908 * Attempt to flush data before changing attributes. We need to do
1908 Flush data before changing file size or changing the last 1909 * this for ATTR_SIZE and ATTR_MTIME for sure, and if we change the
1909 write time of the file on the server. If the 1910 * ownership or mode then we may also need to do this. Here, we take
1910 flush returns error, store it to report later and continue. 1911 * the safe way out and just do the flush on all setattr requests. If
1911 BB: This should be smarter. Why bother flushing pages that 1912 * the flush returns error, store it to report later and continue.
1912 will be truncated anyway? Also, should we error out here if 1913 *
1913 the flush returns error? 1914 * BB: This should be smarter. Why bother flushing pages that
1914 */ 1915 * will be truncated anyway? Also, should we error out here if
1915 rc = filemap_write_and_wait(inode->i_mapping); 1916 * the flush returns error?
1916 if (rc != 0) { 1917 */
1917 cifsInode->write_behind_rc = rc; 1918 rc = filemap_write_and_wait(inode->i_mapping);
1918 rc = 0; 1919 if (rc != 0) {
1919 } 1920 cifsInode->write_behind_rc = rc;
1921 rc = 0;
1920 } 1922 }
1921 1923
1922 if (attrs->ia_valid & ATTR_SIZE) { 1924 if (attrs->ia_valid & ATTR_SIZE) {