From: Nikolay Borisov Date: Thu, 22 Aug 2019 14:24:20 +0000 (+0300) Subject: btrfs: improve error handling in run_delalloc_nocow X-Git-Tag: v5.4-rc1~123^2~38 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=762bf09893b42d1ac8f7f4c02b86e3143b99e61f;p=linux.git btrfs: improve error handling in run_delalloc_nocow Correctly handle failure cases when adding an ordered extents in case of REGULAR or PREALLOC extents. Remove the BUG_ON. Signed-off-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: David Sterba --- diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 90c6a4813a19..b52282df8c4d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1314,6 +1314,8 @@ static noinline int run_delalloc_nocow(struct inode *inode, bool check_prev = true; const bool freespace_inode = btrfs_is_free_space_inode(BTRFS_I(inode)); u64 ino = btrfs_ino(BTRFS_I(inode)); + bool nocow = false; + u64 disk_bytenr = 0; path = btrfs_alloc_path(); if (!path) { @@ -1333,12 +1335,12 @@ static noinline int run_delalloc_nocow(struct inode *inode, struct extent_buffer *leaf; u64 extent_end; u64 extent_offset; - u64 disk_bytenr = 0; u64 num_bytes = 0; u64 disk_num_bytes; u64 ram_bytes; int extent_type; - bool nocow = false; + + nocow = false; ret = btrfs_lookup_file_extent(NULL, root, path, ino, cur_offset, 0); @@ -1572,16 +1574,25 @@ static noinline int run_delalloc_nocow(struct inode *inode, disk_bytenr, num_bytes, num_bytes, BTRFS_ORDERED_PREALLOC); + if (ret) { + btrfs_drop_extent_cache(BTRFS_I(inode), + cur_offset, + cur_offset + num_bytes - 1, + 0); + goto error; + } } else { ret = btrfs_add_ordered_extent(inode, cur_offset, disk_bytenr, num_bytes, num_bytes, BTRFS_ORDERED_NOCOW); + if (ret) + goto error; } if (nocow) btrfs_dec_nocow_writers(fs_info, disk_bytenr); - BUG_ON(ret); /* -ENOMEM */ + nocow = false; if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID) @@ -1626,6 +1637,9 @@ static noinline int run_delalloc_nocow(struct inode *inode, } error: + if (nocow) + btrfs_dec_nocow_writers(fs_info, disk_bytenr); + if (ret && cur_offset < end) extent_clear_unlock_delalloc(inode, cur_offset, end, locked_page, EXTENT_LOCKED |