diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c index 275aa418..95df871a 100644 --- a/btrfs-corrupt-block.c +++ b/btrfs-corrupt-block.c @@ -747,15 +747,8 @@ static void shift_items(struct btrfs_root *root, struct extent_buffer *eb) static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block, char *field) { - struct btrfs_trans_handle *trans; - struct btrfs_root *root; - struct btrfs_path *path; struct extent_buffer *eb; - struct btrfs_key key, root_key; enum btrfs_metadata_block_field corrupt_field; - u64 root_objectid; - u64 orig, bogus; - u8 level; int ret; corrupt_field = convert_metadata_block_field(field); @@ -769,63 +762,78 @@ static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block, fprintf(stderr, "Couldn't read in tree block %s\n", field); return -EINVAL; } - root_objectid = btrfs_header_owner(eb); - level = btrfs_header_level(eb); - if (level) - btrfs_node_key_to_cpu(eb, &key, 0); - else - btrfs_item_key_to_cpu(eb, &key, 0); - free_extent_buffer(eb); - - root_key.objectid = root_objectid; - root_key.type = BTRFS_ROOT_ITEM_KEY; - root_key.offset = (u64)-1; - - root = btrfs_read_fs_root(fs_info, &root_key); - if (IS_ERR(root)) { - fprintf(stderr, "Couldn't find owner root %llu\n", - key.objectid); - return PTR_ERR(root); - } - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - - trans = btrfs_start_transaction(root, 1); - if (IS_ERR(trans)) { - btrfs_free_path(path); - fprintf(stderr, "Couldn't start transaction %ld\n", - PTR_ERR(trans)); - return PTR_ERR(trans); - } - - path->lowest_level = level; - ret = btrfs_search_slot(trans, root, &key, path, 0, 1); - if (ret < 0) { - fprintf(stderr, "Error searching to node %d\n", ret); - goto out; - } - eb = path->nodes[level]; ret = 0; switch (corrupt_field) { case BTRFS_METADATA_BLOCK_GENERATION: - orig = btrfs_header_generation(eb); - bogus = generate_u64(orig); + { + u64 orig = btrfs_header_generation(eb); + u64 bogus = generate_u64(orig); + btrfs_set_header_generation(eb, bogus); + write_and_map_eb(fs_info, eb); + free_extent_buffer(eb); break; + } case BTRFS_METADATA_BLOCK_SHIFT_ITEMS: + { + struct btrfs_trans_handle *trans; + struct btrfs_root *root; + struct btrfs_path *path; + struct btrfs_key key, root_key; + u64 root_objectid; + u8 level; + + root_objectid = btrfs_header_owner(eb); + level = btrfs_header_level(eb); + if (level) + btrfs_node_key_to_cpu(eb, &key, 0); + else + btrfs_item_key_to_cpu(eb, &key, 0); + free_extent_buffer(eb); + + root_key.objectid = root_objectid; + root_key.type = BTRFS_ROOT_ITEM_KEY; + root_key.offset = (u64)-1; + + root = btrfs_read_fs_root(fs_info, &root_key); + if (IS_ERR(root)) { + fprintf(stderr, "Couldn't find owner root %llu\n", + key.objectid); + return PTR_ERR(root); + } + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + trans = btrfs_start_transaction(root, 1); + if (IS_ERR(trans)) { + btrfs_free_path(path); + fprintf(stderr, "Couldn't start transaction %ld\n", + PTR_ERR(trans)); + return PTR_ERR(trans); + } + + path->lowest_level = level; + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); + if (ret < 0) { + fprintf(stderr, "Error searching to node %d\n", ret); + btrfs_free_path(path); + btrfs_abort_transaction(trans, ret); + return ret; + } + eb = path->nodes[level]; shift_items(root, path->nodes[level]); + btrfs_mark_buffer_dirty(path->nodes[level]); + btrfs_commit_transaction(trans, root); break; + } default: ret = -EINVAL; break; } - btrfs_mark_buffer_dirty(path->nodes[level]); -out: - btrfs_commit_transaction(trans, root); - btrfs_free_path(path); + return ret; }