aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/linux-2.6/xfs_aops.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/linux-2.6/xfs_aops.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/linux-2.6/xfs_aops.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c42
1 files changed, 36 insertions, 6 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index bf7aad0d78b8..15412fe15c3a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -1494,6 +1494,22 @@ xfs_vm_direct_IO(
1494 return ret; 1494 return ret;
1495} 1495}
1496 1496
1497STATIC void
1498xfs_vm_write_failed(
1499 struct address_space *mapping,
1500 loff_t to)
1501{
1502 struct inode *inode = mapping->host;
1503
1504 if (to > inode->i_size) {
1505 struct iattr ia = {
1506 .ia_valid = ATTR_SIZE | ATTR_FORCE,
1507 .ia_size = inode->i_size,
1508 };
1509 xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK);
1510 }
1511}
1512
1497STATIC int 1513STATIC int
1498xfs_vm_write_begin( 1514xfs_vm_write_begin(
1499 struct file *file, 1515 struct file *file,
@@ -1508,12 +1524,26 @@ xfs_vm_write_begin(
1508 1524
1509 ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS, 1525 ret = block_write_begin(mapping, pos, len, flags | AOP_FLAG_NOFS,
1510 pagep, xfs_get_blocks); 1526 pagep, xfs_get_blocks);
1511 if (unlikely(ret)) { 1527 if (unlikely(ret))
1512 loff_t isize = mapping->host->i_size; 1528 xfs_vm_write_failed(mapping, pos + len);
1513 if (pos + len > isize) 1529 return ret;
1514 vmtruncate(mapping->host, isize); 1530}
1515 } 1531
1532STATIC int
1533xfs_vm_write_end(
1534 struct file *file,
1535 struct address_space *mapping,
1536 loff_t pos,
1537 unsigned len,
1538 unsigned copied,
1539 struct page *page,
1540 void *fsdata)
1541{
1542 int ret;
1516 1543
1544 ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata);
1545 if (unlikely(ret < len))
1546 xfs_vm_write_failed(mapping, pos + len);
1517 return ret; 1547 return ret;
1518} 1548}
1519 1549
@@ -1559,7 +1589,7 @@ const struct address_space_operations xfs_address_space_operations = {
1559 .releasepage = xfs_vm_releasepage, 1589 .releasepage = xfs_vm_releasepage,
1560 .invalidatepage = xfs_vm_invalidatepage, 1590 .invalidatepage = xfs_vm_invalidatepage,
1561 .write_begin = xfs_vm_write_begin, 1591 .write_begin = xfs_vm_write_begin,
1562 .write_end = generic_write_end, 1592 .write_end = xfs_vm_write_end,
1563 .bmap = xfs_vm_bmap, 1593 .bmap = xfs_vm_bmap,
1564 .direct_IO = xfs_vm_direct_IO, 1594 .direct_IO = xfs_vm_direct_IO,
1565 .migratepage = buffer_migrate_page, 1595 .migratepage = buffer_migrate_page,