diff options
| -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 { |
