diff options
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r-- | fs/cifs/inode.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 37c6ce87416b..86b9dbbd8441 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -143,10 +143,10 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
143 | inode->i_gid = le64_to_cpu(findData.Gid); | 143 | inode->i_gid = le64_to_cpu(findData.Gid); |
144 | inode->i_nlink = le64_to_cpu(findData.Nlinks); | 144 | inode->i_nlink = le64_to_cpu(findData.Nlinks); |
145 | 145 | ||
146 | spin_lock(&inode->i_lock); | ||
146 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { | 147 | if (is_size_safe_to_change(cifsInfo, end_of_file)) { |
147 | /* can not safely change the file size here if the | 148 | /* can not safely change the file size here if the |
148 | client is writing to it due to potential races */ | 149 | client is writing to it due to potential races */ |
149 | |||
150 | i_size_write(inode, end_of_file); | 150 | i_size_write(inode, end_of_file); |
151 | 151 | ||
152 | /* blksize needs to be multiple of two. So safer to default to | 152 | /* blksize needs to be multiple of two. So safer to default to |
@@ -162,6 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode, | |||
162 | /* for this calculation */ | 162 | /* for this calculation */ |
163 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; | 163 | inode->i_blocks = (512 - 1 + num_of_bytes) >> 9; |
164 | } | 164 | } |
165 | spin_unlock(&inode->i_lock); | ||
165 | 166 | ||
166 | if (num_of_bytes < end_of_file) | 167 | if (num_of_bytes < end_of_file) |
167 | cFYI(1, ("allocation size less than end of file")); | 168 | cFYI(1, ("allocation size less than end of file")); |
@@ -496,6 +497,8 @@ int cifs_get_inode_info(struct inode **pinode, | |||
496 | /* BB add code here - | 497 | /* BB add code here - |
497 | validate if device or weird share or device type? */ | 498 | validate if device or weird share or device type? */ |
498 | } | 499 | } |
500 | |||
501 | spin_lock(&inode->i_lock); | ||
499 | if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) { | 502 | if (is_size_safe_to_change(cifsInfo, le64_to_cpu(pfindData->EndOfFile))) { |
500 | /* can not safely shrink the file size here if the | 503 | /* can not safely shrink the file size here if the |
501 | client is writing to it due to potential races */ | 504 | client is writing to it due to potential races */ |
@@ -506,6 +509,7 @@ int cifs_get_inode_info(struct inode **pinode, | |||
506 | inode->i_blocks = (512 - 1 + le64_to_cpu( | 509 | inode->i_blocks = (512 - 1 + le64_to_cpu( |
507 | pfindData->AllocationSize)) >> 9; | 510 | pfindData->AllocationSize)) >> 9; |
508 | } | 511 | } |
512 | spin_unlock(&inode->i_lock); | ||
509 | 513 | ||
510 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); | 514 | inode->i_nlink = le32_to_cpu(pfindData->NumberOfLinks); |
511 | 515 | ||
@@ -834,8 +838,10 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
834 | 838 | ||
835 | if (!rc) { | 839 | if (!rc) { |
836 | drop_nlink(inode); | 840 | drop_nlink(inode); |
841 | spin_lock(&direntry->d_inode->i_lock); | ||
837 | i_size_write(direntry->d_inode,0); | 842 | i_size_write(direntry->d_inode,0); |
838 | clear_nlink(direntry->d_inode); | 843 | clear_nlink(direntry->d_inode); |
844 | spin_unlock(&direntry->d_inode->i_lock); | ||
839 | } | 845 | } |
840 | 846 | ||
841 | cifsInode = CIFS_I(direntry->d_inode); | 847 | cifsInode = CIFS_I(direntry->d_inode); |
@@ -1128,6 +1134,52 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from) | |||
1128 | return rc; | 1134 | return rc; |
1129 | } | 1135 | } |
1130 | 1136 | ||
1137 | static int cifs_vmtruncate(struct inode * inode, loff_t offset) | ||
1138 | { | ||
1139 | struct address_space *mapping = inode->i_mapping; | ||
1140 | unsigned long limit; | ||
1141 | |||
1142 | spin_lock(&inode->i_lock); | ||
1143 | if (inode->i_size < offset) | ||
1144 | goto do_expand; | ||
1145 | /* | ||
1146 | * truncation of in-use swapfiles is disallowed - it would cause | ||
1147 | * subsequent swapout to scribble on the now-freed blocks. | ||
1148 | */ | ||
1149 | if (IS_SWAPFILE(inode)) { | ||
1150 | spin_unlock(&inode->i_lock); | ||
1151 | goto out_busy; | ||
1152 | } | ||
1153 | i_size_write(inode, offset); | ||
1154 | spin_unlock(&inode->i_lock); | ||
1155 | unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1); | ||
1156 | truncate_inode_pages(mapping, offset); | ||
1157 | goto out_truncate; | ||
1158 | |||
1159 | do_expand: | ||
1160 | limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; | ||
1161 | if (limit != RLIM_INFINITY && offset > limit) { | ||
1162 | spin_unlock(&inode->i_lock); | ||
1163 | goto out_sig; | ||
1164 | } | ||
1165 | if (offset > inode->i_sb->s_maxbytes) { | ||
1166 | spin_unlock(&inode->i_lock); | ||
1167 | goto out_big; | ||
1168 | } | ||
1169 | i_size_write(inode, offset); | ||
1170 | spin_unlock(&inode->i_lock); | ||
1171 | out_truncate: | ||
1172 | if (inode->i_op && inode->i_op->truncate) | ||
1173 | inode->i_op->truncate(inode); | ||
1174 | return 0; | ||
1175 | out_sig: | ||
1176 | send_sig(SIGXFSZ, current, 0); | ||
1177 | out_big: | ||
1178 | return -EFBIG; | ||
1179 | out_busy: | ||
1180 | return -ETXTBSY; | ||
1181 | } | ||
1182 | |||
1131 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | 1183 | int cifs_setattr(struct dentry *direntry, struct iattr *attrs) |
1132 | { | 1184 | { |
1133 | int xid; | 1185 | int xid; |
@@ -1244,7 +1296,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1244 | */ | 1296 | */ |
1245 | 1297 | ||
1246 | if (rc == 0) { | 1298 | if (rc == 0) { |
1247 | rc = vmtruncate(direntry->d_inode, attrs->ia_size); | 1299 | rc = cifs_vmtruncate(direntry->d_inode, attrs->ia_size); |
1248 | cifs_truncate_page(direntry->d_inode->i_mapping, | 1300 | cifs_truncate_page(direntry->d_inode->i_mapping, |
1249 | direntry->d_inode->i_size); | 1301 | direntry->d_inode->i_size); |
1250 | } else | 1302 | } else |
@@ -1379,9 +1431,11 @@ cifs_setattr_exit: | |||
1379 | return rc; | 1431 | return rc; |
1380 | } | 1432 | } |
1381 | 1433 | ||
1434 | #if 0 | ||
1382 | void cifs_delete_inode(struct inode *inode) | 1435 | void cifs_delete_inode(struct inode *inode) |
1383 | { | 1436 | { |
1384 | cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode)); | 1437 | cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode)); |
1385 | /* may have to add back in if and when safe distributed caching of | 1438 | /* may have to add back in if and when safe distributed caching of |
1386 | directories added e.g. via FindNotify */ | 1439 | directories added e.g. via FindNotify */ |
1387 | } | 1440 | } |
1441 | #endif | ||