diff options
author | Nikolay Borisov <nborisov@suse.com> | 2018-01-08 03:59:43 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-03-01 10:16:00 -0500 |
commit | ac01f26a27f10aace4bb89fd2c2c05a60c251832 (patch) | |
tree | ec27915237f6e7ad42d31193b175d9bff0d5a036 | |
parent | a8fd1f71749387c9a1053a83ff1c16287499a4e7 (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.c | 11 |
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); |