summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Borisov <nborisov@suse.com>2019-08-22 17:24:20 +0300
committerDavid Sterba <dsterba@suse.com>2019-09-09 15:59:14 +0300
commit762bf09893b42d1ac8f7f4c02b86e3143b99e61f (patch)
treec233f6e6e22d48a4d11749bbc5c9d8b750bd0eb1
parente8e210075a901aac577fd33619509dfb21a07071 (diff)
downloadlinux-762bf09893b42d1ac8f7f4c02b86e3143b99e61f.tar.xz
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 <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/inode.c20
1 files changed, 17 insertions, 3 deletions
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 @@ out_check:
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 @@ out_check:
}
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 |