diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 6f420c8efdaf..0ec8e228b89f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -7546,7 +7546,7 @@ static void unuse_block_rsv(struct btrfs_fs_info *fs_info, | |||
7546 | * returns the key for the extent through ins, and a tree buffer for | 7546 | * returns the key for the extent through ins, and a tree buffer for |
7547 | * the first block of the extent through buf. | 7547 | * the first block of the extent through buf. |
7548 | * | 7548 | * |
7549 | * returns the tree buffer or NULL. | 7549 | * returns the tree buffer or an ERR_PTR on error. |
7550 | */ | 7550 | */ |
7551 | struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, | 7551 | struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, |
7552 | struct btrfs_root *root, | 7552 | struct btrfs_root *root, |
@@ -7557,6 +7557,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, | |||
7557 | struct btrfs_key ins; | 7557 | struct btrfs_key ins; |
7558 | struct btrfs_block_rsv *block_rsv; | 7558 | struct btrfs_block_rsv *block_rsv; |
7559 | struct extent_buffer *buf; | 7559 | struct extent_buffer *buf; |
7560 | struct btrfs_delayed_extent_op *extent_op; | ||
7560 | u64 flags = 0; | 7561 | u64 flags = 0; |
7561 | int ret; | 7562 | int ret; |
7562 | u32 blocksize = root->nodesize; | 7563 | u32 blocksize = root->nodesize; |
@@ -7577,13 +7578,14 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, | |||
7577 | 7578 | ||
7578 | ret = btrfs_reserve_extent(root, blocksize, blocksize, | 7579 | ret = btrfs_reserve_extent(root, blocksize, blocksize, |
7579 | empty_size, hint, &ins, 0, 0); | 7580 | empty_size, hint, &ins, 0, 0); |
7580 | if (ret) { | 7581 | if (ret) |
7581 | unuse_block_rsv(root->fs_info, block_rsv, blocksize); | 7582 | goto out_unuse; |
7582 | return ERR_PTR(ret); | ||
7583 | } | ||
7584 | 7583 | ||
7585 | buf = btrfs_init_new_buffer(trans, root, ins.objectid, level); | 7584 | buf = btrfs_init_new_buffer(trans, root, ins.objectid, level); |
7586 | BUG_ON(IS_ERR(buf)); /* -ENOMEM */ | 7585 | if (IS_ERR(buf)) { |
7586 | ret = PTR_ERR(buf); | ||
7587 | goto out_free_reserved; | ||
7588 | } | ||
7587 | 7589 | ||
7588 | if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { | 7590 | if (root_objectid == BTRFS_TREE_RELOC_OBJECTID) { |
7589 | if (parent == 0) | 7591 | if (parent == 0) |
@@ -7593,9 +7595,11 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, | |||
7593 | BUG_ON(parent > 0); | 7595 | BUG_ON(parent > 0); |
7594 | 7596 | ||
7595 | if (root_objectid != BTRFS_TREE_LOG_OBJECTID) { | 7597 | if (root_objectid != BTRFS_TREE_LOG_OBJECTID) { |
7596 | struct btrfs_delayed_extent_op *extent_op; | ||
7597 | extent_op = btrfs_alloc_delayed_extent_op(); | 7598 | extent_op = btrfs_alloc_delayed_extent_op(); |
7598 | BUG_ON(!extent_op); /* -ENOMEM */ | 7599 | if (!extent_op) { |
7600 | ret = -ENOMEM; | ||
7601 | goto out_free_buf; | ||
7602 | } | ||
7599 | if (key) | 7603 | if (key) |
7600 | memcpy(&extent_op->key, key, sizeof(extent_op->key)); | 7604 | memcpy(&extent_op->key, key, sizeof(extent_op->key)); |
7601 | else | 7605 | else |
@@ -7610,13 +7614,24 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, | |||
7610 | extent_op->level = level; | 7614 | extent_op->level = level; |
7611 | 7615 | ||
7612 | ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, | 7616 | ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, |
7613 | ins.objectid, | 7617 | ins.objectid, ins.offset, |
7614 | ins.offset, parent, root_objectid, | 7618 | parent, root_objectid, level, |
7615 | level, BTRFS_ADD_DELAYED_EXTENT, | 7619 | BTRFS_ADD_DELAYED_EXTENT, |
7616 | extent_op, 0); | 7620 | extent_op, 0); |
7617 | BUG_ON(ret); /* -ENOMEM */ | 7621 | if (ret) |
7622 | goto out_free_delayed; | ||
7618 | } | 7623 | } |
7619 | return buf; | 7624 | return buf; |
7625 | |||
7626 | out_free_delayed: | ||
7627 | btrfs_free_delayed_extent_op(extent_op); | ||
7628 | out_free_buf: | ||
7629 | free_extent_buffer(buf); | ||
7630 | out_free_reserved: | ||
7631 | btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 0); | ||
7632 | out_unuse: | ||
7633 | unuse_block_rsv(root->fs_info, block_rsv, blocksize); | ||
7634 | return ERR_PTR(ret); | ||
7620 | } | 7635 | } |
7621 | 7636 | ||
7622 | struct walk_control { | 7637 | struct walk_control { |