diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 77 |
1 files changed, 42 insertions, 35 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index f121a80fdd6f..f36b4e40e443 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -143,6 +143,7 @@ static void cifs_unix_info_to_inode(struct inode *inode, | |||
143 | 143 | ||
144 | inode->i_nlink = le64_to_cpu(info->Nlinks); | 144 | inode->i_nlink = le64_to_cpu(info->Nlinks); |
145 | 145 | ||
146 | cifsInfo->server_eof = end_of_file; | ||
146 | spin_lock(&inode->i_lock); | 147 | spin_lock(&inode->i_lock); |
147 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 148 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
148 | /* | 149 | /* |
@@ -276,7 +277,8 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
276 | 277 | ||
277 | /* get new inode */ | 278 | /* get new inode */ |
278 | if (*pinode == NULL) { | 279 | if (*pinode == NULL) { |
279 | *pinode = cifs_new_inode(sb, &find_data.UniqueId); | 280 | __u64 unique_id = le64_to_cpu(find_data.UniqueId); |
281 | *pinode = cifs_new_inode(sb, &unique_id); | ||
280 | if (*pinode == NULL) { | 282 | if (*pinode == NULL) { |
281 | rc = -ENOMEM; | 283 | rc = -ENOMEM; |
282 | goto cgiiu_exit; | 284 | goto cgiiu_exit; |
@@ -605,12 +607,12 @@ int cifs_get_inode_info(struct inode **pinode, | |||
605 | inode->i_mode |= S_IFREG; | 607 | inode->i_mode |= S_IFREG; |
606 | } | 608 | } |
607 | 609 | ||
610 | cifsInfo->server_eof = le64_to_cpu(pfindData->EndOfFile); | ||
608 | spin_lock(&inode->i_lock); | 611 | spin_lock(&inode->i_lock); |
609 | if (is_size_safe_to_change(cifsInfo, | 612 | if (is_size_safe_to_change(cifsInfo, cifsInfo->server_eof)) { |
610 | le64_to_cpu(pfindData->EndOfFile))) { | ||
611 | /* can not safely shrink the file size here if the | 613 | /* can not safely shrink the file size here if the |
612 | client is writing to it due to potential races */ | 614 | client is writing to it due to potential races */ |
613 | i_size_write(inode, le64_to_cpu(pfindData->EndOfFile)); | 615 | i_size_write(inode, cifsInfo->server_eof); |
614 | 616 | ||
615 | /* 512 bytes (2**9) is the fake blocksize that must be | 617 | /* 512 bytes (2**9) is the fake blocksize that must be |
616 | used for this calculation */ | 618 | used for this calculation */ |
@@ -1138,6 +1140,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1138 | cFYI(1, ("posix mkdir returned 0x%x", rc)); | 1140 | cFYI(1, ("posix mkdir returned 0x%x", rc)); |
1139 | d_drop(direntry); | 1141 | d_drop(direntry); |
1140 | } else { | 1142 | } else { |
1143 | __u64 unique_id; | ||
1141 | if (pInfo->Type == cpu_to_le32(-1)) { | 1144 | if (pInfo->Type == cpu_to_le32(-1)) { |
1142 | /* no return info, go query for it */ | 1145 | /* no return info, go query for it */ |
1143 | kfree(pInfo); | 1146 | kfree(pInfo); |
@@ -1151,8 +1154,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
1151 | else | 1154 | else |
1152 | direntry->d_op = &cifs_dentry_ops; | 1155 | direntry->d_op = &cifs_dentry_ops; |
1153 | 1156 | ||
1154 | newinode = cifs_new_inode(inode->i_sb, | 1157 | unique_id = le64_to_cpu(pInfo->UniqueId); |
1155 | &pInfo->UniqueId); | 1158 | newinode = cifs_new_inode(inode->i_sb, &unique_id); |
1156 | if (newinode == NULL) { | 1159 | if (newinode == NULL) { |
1157 | kfree(pInfo); | 1160 | kfree(pInfo); |
1158 | goto mkdir_get_info; | 1161 | goto mkdir_get_info; |
@@ -1450,7 +1453,8 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
1450 | checking the UniqueId via FILE_INTERNAL_INFO */ | 1453 | checking the UniqueId via FILE_INTERNAL_INFO */ |
1451 | 1454 | ||
1452 | unlink_target: | 1455 | unlink_target: |
1453 | if ((rc == -EACCES) || (rc == -EEXIST)) { | 1456 | /* Try unlinking the target dentry if it's not negative */ |
1457 | if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) { | ||
1454 | tmprc = cifs_unlink(target_dir, target_dentry); | 1458 | tmprc = cifs_unlink(target_dir, target_dentry); |
1455 | if (tmprc) | 1459 | if (tmprc) |
1456 | goto cifs_rename_exit; | 1460 | goto cifs_rename_exit; |
@@ -1753,6 +1757,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs, | |||
1753 | } | 1757 | } |
1754 | 1758 | ||
1755 | if (rc == 0) { | 1759 | if (rc == 0) { |
1760 | cifsInode->server_eof = attrs->ia_size; | ||
1756 | rc = cifs_vmtruncate(inode, attrs->ia_size); | 1761 | rc = cifs_vmtruncate(inode, attrs->ia_size); |
1757 | cifs_truncate_page(inode->i_mapping, inode->i_size); | 1762 | cifs_truncate_page(inode->i_mapping, inode->i_size); |
1758 | } | 1763 | } |
@@ -1792,20 +1797,21 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1792 | goto out; | 1797 | goto out; |
1793 | } | 1798 | } |
1794 | 1799 | ||
1795 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | 1800 | /* |
1796 | /* | 1801 | * Attempt to flush data before changing attributes. We need to do |
1797 | Flush data before changing file size or changing the last | 1802 | * 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 | 1803 | * 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. | 1804 | * 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 | 1805 | * the flush returns error, store it to report later and continue. |
1801 | will be truncated anyway? Also, should we error out here if | 1806 | * |
1802 | the flush returns error? | 1807 | * BB: This should be smarter. Why bother flushing pages that |
1803 | */ | 1808 | * will be truncated anyway? Also, should we error out here if |
1804 | rc = filemap_write_and_wait(inode->i_mapping); | 1809 | * the flush returns error? |
1805 | if (rc != 0) { | 1810 | */ |
1806 | cifsInode->write_behind_rc = rc; | 1811 | rc = filemap_write_and_wait(inode->i_mapping); |
1807 | rc = 0; | 1812 | if (rc != 0) { |
1808 | } | 1813 | cifsInode->write_behind_rc = rc; |
1814 | rc = 0; | ||
1809 | } | 1815 | } |
1810 | 1816 | ||
1811 | if (attrs->ia_valid & ATTR_SIZE) { | 1817 | if (attrs->ia_valid & ATTR_SIZE) { |
@@ -1903,20 +1909,21 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
1903 | return -ENOMEM; | 1909 | return -ENOMEM; |
1904 | } | 1910 | } |
1905 | 1911 | ||
1906 | if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) { | 1912 | /* |
1907 | /* | 1913 | * Attempt to flush data before changing attributes. We need to do |
1908 | Flush data before changing file size or changing the last | 1914 | * 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 | 1915 | * 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. | 1916 | * 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 | 1917 | * the flush returns error, store it to report later and continue. |
1912 | will be truncated anyway? Also, should we error out here if | 1918 | * |
1913 | the flush returns error? | 1919 | * BB: This should be smarter. Why bother flushing pages that |
1914 | */ | 1920 | * will be truncated anyway? Also, should we error out here if |
1915 | rc = filemap_write_and_wait(inode->i_mapping); | 1921 | * the flush returns error? |
1916 | if (rc != 0) { | 1922 | */ |
1917 | cifsInode->write_behind_rc = rc; | 1923 | rc = filemap_write_and_wait(inode->i_mapping); |
1918 | rc = 0; | 1924 | if (rc != 0) { |
1919 | } | 1925 | cifsInode->write_behind_rc = rc; |
1926 | rc = 0; | ||
1920 | } | 1927 | } |
1921 | 1928 | ||
1922 | if (attrs->ia_valid & ATTR_SIZE) { | 1929 | if (attrs->ia_valid & ATTR_SIZE) { |