btrfs: fix insert_reserved error handling
authorJosef Bacik <josef@toxicpanda.com>
Thu, 11 Oct 2018 19:54:22 +0000 (15:54 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2018 19:08:59 +0000 (11:08 -0800)
commit 80ee54bfe8a3850015585ebc84e8d207fcae6831 upstream.

We were not handling the reserved byte accounting properly for data
references.  Metadata was fine, if it errored out the error paths would
free the bytes_reserved count and pin the extent, but it even missed one
of the error cases.  So instead move this handling up into
run_one_delayed_ref so we are sure that both cases are properly cleaned
up in case of a transaction abort.

CC: stable@vger.kernel.org # 4.18+
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/btrfs/extent-tree.c

index a43554b..51e41e5 100644 (file)
@@ -2366,6 +2366,9 @@ static int run_one_delayed_ref(struct btrfs_trans_handle *trans,
                                           insert_reserved);
        else
                BUG();
+       if (ret && insert_reserved)
+               btrfs_pin_extent(trans->fs_info, node->bytenr,
+                                node->num_bytes, 1);
        return ret;
 }
 
@@ -7977,21 +7980,14 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
        }
 
        path = btrfs_alloc_path();
-       if (!path) {
-               btrfs_free_and_pin_reserved_extent(fs_info,
-                                                  extent_key.objectid,
-                                                  fs_info->nodesize);
+       if (!path)
                return -ENOMEM;
-       }
 
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
                                      &extent_key, size);
        if (ret) {
                btrfs_free_path(path);
-               btrfs_free_and_pin_reserved_extent(fs_info,
-                                                  extent_key.objectid,
-                                                  fs_info->nodesize);
                return ret;
        }