X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=free-space-tree.c;h=69a4eca8a74fe80776592f9ccfcf052758a2589c;hb=f5dd778f5299088f89d380ce922a84d77a98b9d6;hp=a323e8aae99797ef248d3703cfebe0c51872e38a;hpb=e4797df6a9fac329fdb168f8fd6bf1925ead3c28;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/free-space-tree.c b/free-space-tree.c index a323e8a..69a4eca 100644 --- a/free-space-tree.c +++ b/free-space-tree.c @@ -20,6 +20,7 @@ #include "disk-io.h" #include "free-space-cache.h" #include "free-space-tree.h" +#include "transaction.h" static struct btrfs_free_space_info * search_free_space_info(struct btrfs_trans_handle *trans, @@ -67,6 +68,91 @@ static int free_space_test_bit(struct btrfs_block_group_cache *block_group, return !!extent_buffer_test_bit(leaf, ptr, i); } +static int clear_free_space_tree(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + struct btrfs_path *path; + struct btrfs_key key; + int nr; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + key.objectid = 0; + key.type = 0; + key.offset = 0; + + while (1) { + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret < 0) + goto out; + + nr = btrfs_header_nritems(path->nodes[0]); + if (!nr) + break; + + path->slots[0] = 0; + ret = btrfs_del_items(trans, root, path, 0, nr); + if (ret) + goto out; + + btrfs_release_path(path); + } + + ret = 0; +out: + btrfs_free_path(path); + return ret; +} + +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) +{ + struct btrfs_trans_handle *trans; + struct btrfs_root *tree_root = fs_info->tree_root; + struct btrfs_root *free_space_root = fs_info->free_space_root; + int ret; + u64 features; + + trans = btrfs_start_transaction(tree_root, 0); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + features = btrfs_super_compat_ro_flags(fs_info->super_copy); + features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID | + BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE); + btrfs_set_super_compat_ro_flags(fs_info->super_copy, features); + fs_info->free_space_root = NULL; + + ret = clear_free_space_tree(trans, free_space_root); + if (ret) + goto abort; + + ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key); + if (ret) + goto abort; + + list_del(&free_space_root->dirty_list); + + ret = clean_tree_block(trans, tree_root, free_space_root->node); + if (ret) + goto abort; + ret = btrfs_free_tree_block(trans, free_space_root, + free_space_root->node, 0, 1); + if (ret) + goto abort; + + free_extent_buffer(free_space_root->node); + free_extent_buffer(free_space_root->commit_root); + kfree(free_space_root); + + ret = btrfs_commit_transaction(trans, tree_root); + +abort: + return ret; +} + static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path, @@ -102,13 +188,15 @@ static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info, break; } if (key.objectid >= end) { - fprintf(stderr, "free space bitmap starts at %Lu, beyond end of block group %Lu-%Lu\n", + fprintf(stderr, + "free space bitmap starts at %llu, beyond end of block group %llu-%llu\n", key.objectid, start, end); (*errors)++; break; } if (key.objectid + key.offset > end) { - fprintf(stderr, "free space bitmap ends at %Lu, beyond end of block group %Lu-%Lu\n", + fprintf(stderr, + "free space bitmap ends at %llu, beyond end of block group %llu-%llu\n", key.objectid, start, end); (*errors)++; break; @@ -117,7 +205,7 @@ static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info, offset = key.objectid; while (offset < key.objectid + key.offset) { bit = free_space_test_bit(block_group, path, offset, - root->sectorsize); + fs_info->sectorsize); if (prev_bit == 0 && bit == 1) { extent_start = offset; } else if (prev_bit == 1 && bit == 0) { @@ -125,7 +213,7 @@ static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info, extent_count++; } prev_bit = bit; - offset += root->sectorsize; + offset += fs_info->sectorsize; } } @@ -179,13 +267,15 @@ static int load_free_space_extents(struct btrfs_fs_info *fs_info, break; } if (key.objectid >= end) { - fprintf(stderr, "free space extent starts at %Lu, beyond end of block group %Lu-%Lu\n", + fprintf(stderr, + "free space extent starts at %llu, beyond end of block group %llu-%llu\n", key.objectid, start, end); (*errors)++; break; } if (key.objectid + key.offset > end) { - fprintf(stderr, "free space extent ends at %Lu, beyond end of block group %Lu-%Lu\n", + fprintf(stderr, + "free space extent ends at %llu, beyond end of block group %llu-%llu\n", key.objectid, start, end); (*errors)++; break; @@ -198,12 +288,14 @@ static int load_free_space_extents(struct btrfs_fs_info *fs_info, u64 prev_end = prev_start + prev_key.offset; if (cur_start < prev_end) { - fprintf(stderr, "free space extent %Lu-%Lu overlaps with previous %Lu-%Lu\n", + fprintf(stderr, + "free space extent %llu-%llu overlaps with previous %llu-%llu\n", cur_start, cur_end, prev_start, prev_end); (*errors)++; } else if (cur_start == prev_end) { - fprintf(stderr, "free space extent %Lu-%Lu is unmerged with previous %Lu-%Lu\n", + fprintf(stderr, + "free space extent %llu-%llu is unmerged with previous %llu-%llu\n", cur_start, cur_end, prev_start, prev_end); (*errors)++;