diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-06-14 05:17:31 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-09 16:47:42 -0400 |
commit | fa9b227e9019ebaeeb06224ba531a490f91144b3 (patch) | |
tree | ff3644c6572d2b22db0d8b71f1a79ae0ad33d102 /fs/xfs/linux-2.6 | |
parent | 2f246fd0f126f3b3c23a4e6b7109350e83356bd6 (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')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 42 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 16 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_linux.h | 2 |
3 files changed, 36 insertions, 24 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 | ||
1497 | STATIC void | ||
1498 | xfs_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 | |||
1497 | STATIC int | 1513 | STATIC int |
1498 | xfs_vm_write_begin( | 1514 | xfs_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 | |
1532 | STATIC int | ||
1533 | xfs_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, |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 536b81e63a3d..62dd349facee 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -540,21 +540,6 @@ xfs_vn_setattr( | |||
540 | return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0); | 540 | return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0); |
541 | } | 541 | } |
542 | 542 | ||
543 | /* | ||
544 | * block_truncate_page can return an error, but we can't propagate it | ||
545 | * at all here. Leave a complaint + stack trace in the syslog because | ||
546 | * this could be bad. If it is bad, we need to propagate the error further. | ||
547 | */ | ||
548 | STATIC void | ||
549 | xfs_vn_truncate( | ||
550 | struct inode *inode) | ||
551 | { | ||
552 | int error; | ||
553 | error = block_truncate_page(inode->i_mapping, inode->i_size, | ||
554 | xfs_get_blocks); | ||
555 | WARN_ON(error); | ||
556 | } | ||
557 | |||
558 | STATIC long | 543 | STATIC long |
559 | xfs_vn_fallocate( | 544 | xfs_vn_fallocate( |
560 | struct inode *inode, | 545 | struct inode *inode, |
@@ -694,7 +679,6 @@ xfs_vn_fiemap( | |||
694 | 679 | ||
695 | static const struct inode_operations xfs_inode_operations = { | 680 | static const struct inode_operations xfs_inode_operations = { |
696 | .check_acl = xfs_check_acl, | 681 | .check_acl = xfs_check_acl, |
697 | .truncate = xfs_vn_truncate, | ||
698 | .getattr = xfs_vn_getattr, | 682 | .getattr = xfs_vn_getattr, |
699 | .setattr = xfs_vn_setattr, | 683 | .setattr = xfs_vn_setattr, |
700 | .setxattr = generic_setxattr, | 684 | .setxattr = generic_setxattr, |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 998a9d7fb9c8..2fa0bd9ebc7f 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -156,8 +156,6 @@ | |||
156 | */ | 156 | */ |
157 | #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) | 157 | #define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL) |
158 | #define xfs_stack_trace() dump_stack() | 158 | #define xfs_stack_trace() dump_stack() |
159 | #define xfs_itruncate_data(ip, off) \ | ||
160 | (-vmtruncate(VFS_I(ip), (off))) | ||
161 | 159 | ||
162 | 160 | ||
163 | /* Move the kernel do_div definition off to one side */ | 161 | /* Move the kernel do_div definition off to one side */ |