diff options
author | Jeff Layton <jlayton@redhat.com> | 2009-03-26 13:35:37 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-04-16 21:26:48 -0400 |
commit | 0f4d634c59a4e062bef81c00d9e63333f2a83b46 (patch) | |
tree | b71dbcddf45eee405ea9bb615ef621b9a09a9994 /fs/cifs/inode.c | |
parent | 20d9207849d5abe60461841b3c3724f6e7c9d33e (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.c | 58 |
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) { |