aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-06-14 05:17:31 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-08-09 16:47:42 -0400
commitfa9b227e9019ebaeeb06224ba531a490f91144b3 (patch)
treeff3644c6572d2b22db0d8b71f1a79ae0ad33d102 /fs/xfs/xfs_vnodeops.c
parent2f246fd0f126f3b3c23a4e6b7109350e83356bd6 (diff)
xfs: new truncate sequence
Convert XFS to the new truncate sequence. We still can have errors after updating the file size in xfs_setattr, but these are real I/O errors and lead to a transaction abort and filesystem shutdown, so they are not an issue. Errors from ->write_begin and write_end can now be handled correctly because we can actually get rid of the delalloc extents while previous the buffer state was stipped in block_invalidatepage. There is still no error handling for ->direct_IO, because doing so will need some major restructuring given that we only have the iolock shared and do not hold i_mutex at all. Fortunately leaving the normally allocated blocks behind there is not a major issue and this will get cleaned up by xfs_free_eofblock later. Note: the patch is against Al's vfs.git tree as that contains the nessecary preparations. I'd prefer to get it applied there so that we can get some testing in linux-next. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c38
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);