diff options
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 3ac137dd531b..66d585c6917c 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -221,8 +221,11 @@ xfs_setattr( | |||
221 | * transaction to modify the i_size. | 221 | * transaction to modify the i_size. |
222 | */ | 222 | */ |
223 | code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size); | 223 | code = xfs_zero_eof(ip, iattr->ia_size, ip->i_size); |
224 | if (code) | ||
225 | goto error_return; | ||
224 | } | 226 | } |
225 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 227 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
228 | lock_flags &= ~XFS_ILOCK_EXCL; | ||
226 | 229 | ||
227 | /* | 230 | /* |
228 | * We are going to log the inode size change in this | 231 | * We are going to log the inode size change in this |
@@ -236,36 +239,35 @@ xfs_setattr( | |||
236 | * really care about here and prevents waiting for other data | 239 | * really care about here and prevents waiting for other data |
237 | * not within the range we care about here. | 240 | * not within the range we care about here. |
238 | */ | 241 | */ |
239 | if (!code && | 242 | if (ip->i_size != ip->i_d.di_size && |
240 | ip->i_size != ip->i_d.di_size && | ||
241 | iattr->ia_size > ip->i_d.di_size) { | 243 | iattr->ia_size > ip->i_d.di_size) { |
242 | code = xfs_flush_pages(ip, | 244 | code = xfs_flush_pages(ip, |
243 | ip->i_d.di_size, iattr->ia_size, | 245 | ip->i_d.di_size, iattr->ia_size, |
244 | XBF_ASYNC, FI_NONE); | 246 | XBF_ASYNC, FI_NONE); |
247 | if (code) | ||
248 | goto error_return; | ||
245 | } | 249 | } |
246 | 250 | ||
247 | /* wait for all I/O to complete */ | 251 | /* wait for all I/O to complete */ |
248 | xfs_ioend_wait(ip); | 252 | xfs_ioend_wait(ip); |
249 | 253 | ||
250 | if (!code) | 254 | code = -block_truncate_page(inode->i_mapping, iattr->ia_size, |
251 | code = xfs_itruncate_data(ip, iattr->ia_size); | 255 | xfs_get_blocks); |
252 | if (code) { | 256 | if (code) |
253 | ASSERT(tp == NULL); | ||
254 | lock_flags &= ~XFS_ILOCK_EXCL; | ||
255 | ASSERT(lock_flags == XFS_IOLOCK_EXCL || !need_iolock); | ||
256 | goto error_return; | 257 | goto error_return; |
257 | } | 258 | |
258 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); | 259 | tp = xfs_trans_alloc(mp, XFS_TRANS_SETATTR_SIZE); |
259 | if ((code = xfs_trans_reserve(tp, 0, | 260 | code = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, |
260 | XFS_ITRUNCATE_LOG_RES(mp), 0, | 261 | XFS_TRANS_PERM_LOG_RES, |
261 | XFS_TRANS_PERM_LOG_RES, | 262 | XFS_ITRUNCATE_LOG_COUNT); |
262 | XFS_ITRUNCATE_LOG_COUNT))) { | 263 | if (code) |
263 | xfs_trans_cancel(tp, 0); | 264 | goto error_return; |
264 | if (need_iolock) | 265 | |
265 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 266 | truncate_setsize(inode, iattr->ia_size); |
266 | return code; | 267 | |
267 | } | ||
268 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; | 268 | commit_flags = XFS_TRANS_RELEASE_LOG_RES; |
269 | lock_flags |= XFS_ILOCK_EXCL; | ||
270 | |||
269 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 271 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
270 | 272 | ||
271 | xfs_trans_ijoin(tp, ip); | 273 | xfs_trans_ijoin(tp, ip); |