aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikolay Borisov <nborisov@suse.com>2018-01-08 03:59:43 -0500
committerDavid Sterba <dsterba@suse.com>2018-03-01 10:16:00 -0500
commitac01f26a27f10aace4bb89fd2c2c05a60c251832 (patch)
treeec27915237f6e7ad42d31193b175d9bff0d5a036
parenta8fd1f71749387c9a1053a83ff1c16287499a4e7 (diff)
btrfs: handle failure of add_pending_csums
add_pending_csums was added as part of the new data=ordered implementation in e6dcd2dc9c48 ("Btrfs: New data=ordered implementation"). Even back then it called the btrfs_csum_file_blocks which can fail but it never bothered handling the failure. In ENOMEM situation this could lead to the filesystem failing to write the checksums for a particular extent and not detect this. On read this could lead to the filesystem erroring out due to crc mismatch. Fix it by propagating failure from add_pending_csums and handling them. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: Josef Bacik <jbacik@fb.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/inode.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 29b491328f4e..8f7d41fcfbff 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2042,12 +2042,15 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
2042 struct inode *inode, struct list_head *list) 2042 struct inode *inode, struct list_head *list)
2043{ 2043{
2044 struct btrfs_ordered_sum *sum; 2044 struct btrfs_ordered_sum *sum;
2045 int ret;
2045 2046
2046 list_for_each_entry(sum, list, list) { 2047 list_for_each_entry(sum, list, list) {
2047 trans->adding_csums = true; 2048 trans->adding_csums = true;
2048 btrfs_csum_file_blocks(trans, 2049 ret = btrfs_csum_file_blocks(trans,
2049 BTRFS_I(inode)->root->fs_info->csum_root, sum); 2050 BTRFS_I(inode)->root->fs_info->csum_root, sum);
2050 trans->adding_csums = false; 2051 trans->adding_csums = false;
2052 if (ret)
2053 return ret;
2051 } 2054 }
2052 return 0; 2055 return 0;
2053} 2056}
@@ -3061,7 +3064,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
3061 goto out; 3064 goto out;
3062 } 3065 }
3063 3066
3064 add_pending_csums(trans, inode, &ordered_extent->list); 3067 ret = add_pending_csums(trans, inode, &ordered_extent->list);
3068 if (ret) {
3069 btrfs_abort_transaction(trans, ret);
3070 goto out;
3071 }
3065 3072
3066 btrfs_ordered_update_i_size(inode, 0, ordered_extent); 3073 btrfs_ordered_update_i_size(inode, 0, ordered_extent);
3067 ret = btrfs_update_inode_fallback(trans, root, inode); 3074 ret = btrfs_update_inode_fallback(trans, root, inode);