From 50860d6e31c28cf4789ef099729dfbce2108620a Mon Sep 17 00:00:00 2001 From: Yan Zheng Date: Wed, 3 Jun 2009 11:59:47 -0400 Subject: [PATCH] Update converter for the new format Signed-off-by: Yan Zheng Signed-off-by: Chris Mason --- convert.c | 264 ++++++++++++++++++++++++---------------------------------- ctree.c | 17 ++-- disk-io.c | 8 ++ extent-tree.c | 24 ++++-- 4 files changed, 145 insertions(+), 168 deletions(-) diff --git a/convert.c b/convert.c index 9f466031..d2c9efa9 100644 --- a/convert.c +++ b/convert.c @@ -141,6 +141,9 @@ static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs) bytenr + STRIPE_LEN - 1, 0); } + clear_extent_dirty(&root->fs_info->free_space_cache, + 0, BTRFS_SUPER_INFO_OFFSET - 1, 0); + return 0; } @@ -364,7 +367,7 @@ static int record_file_extent(struct btrfs_trans_handle *trans, struct btrfs_file_extent_item *fi; struct btrfs_key ins_key; struct btrfs_path path; - struct btrfs_extent_item extent_item; + struct btrfs_extent_item *ei; u32 blocksize = root->sectorsize; u64 nbytes; u64 bytes_used; @@ -432,13 +435,25 @@ static int record_file_extent(struct btrfs_trans_handle *trans, bytes_used = btrfs_root_used(&root->root_item); btrfs_set_root_used(&root->root_item, bytes_used + num_bytes); + btrfs_release_path(root, &path); + ins_key.objectid = disk_bytenr; ins_key.offset = num_bytes; - btrfs_set_key_type(&ins_key, BTRFS_EXTENT_ITEM_KEY); - btrfs_set_stack_extent_refs(&extent_item, 0); - ret = btrfs_insert_item(trans, extent_root, &ins_key, - &extent_item, sizeof(extent_item)); + ins_key.type = BTRFS_EXTENT_ITEM_KEY; + + ret = btrfs_insert_empty_item(trans, extent_root, &path, + &ins_key, sizeof(*ei)); if (ret == 0) { + leaf = path.nodes[0]; + ei = btrfs_item_ptr(leaf, path.slots[0], + struct btrfs_extent_item); + + btrfs_set_extent_refs(leaf, ei, 0); + btrfs_set_extent_generation(leaf, ei, 0); + btrfs_set_extent_flags(leaf, ei, BTRFS_EXTENT_FLAG_DATA); + + btrfs_mark_buffer_dirty(leaf); + bytes_used = btrfs_super_bytes_used(&info->super_copy); btrfs_set_super_bytes_used(&info->super_copy, bytes_used + num_bytes); @@ -451,9 +466,9 @@ static int record_file_extent(struct btrfs_trans_handle *trans, } btrfs_extent_post_op(trans, extent_root); - ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, - leaf->start, root->root_key.objectid, - trans->transid, objectid); + ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, 0, + root->root_key.objectid, + objectid, file_pos); if (ret) goto fail; ret = 0; @@ -1239,17 +1254,16 @@ static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs, struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *extent_root = fs_info->extent_root; struct btrfs_trans_handle *trans; - struct btrfs_extent_ref *ref_item; + struct btrfs_extent_item *ei; + struct btrfs_extent_inline_ref *iref; + struct btrfs_extent_data_ref *dref; u64 bytenr; u64 num_bytes; - u64 ref_root; - u64 ref_owner; u64 objectid; u64 last_byte; u64 first_free; u64 total_bytes; u32 sectorsize = root->sectorsize; - int file_extent; total_bytes = btrfs_super_total_bytes(&fs_info->super_copy); first_free = BTRFS_SUPER_INFO_OFFSET + sectorsize * 2 - 1; @@ -1315,43 +1329,28 @@ next: path.slots[0]++; goto next; } - /* - * Check backref to distinguish extent items for normal - * files (files that correspond to files in Ext2fs) from - * extent items for ctree blocks. - */ + bytenr = key.objectid; num_bytes = key.offset; - file_extent = 0; - while (1) { - if (path.slots[0] >= btrfs_header_nritems(leaf)) { - ret = btrfs_next_leaf(extent_root, &path); - if (ret > 0) - break; - if (ret < 0) - goto fail; - leaf = path.nodes[0]; - } - btrfs_item_key_to_cpu(leaf, &key, path.slots[0]); - if (key.objectid != bytenr) - break; - if (key.type != BTRFS_EXTENT_REF_KEY) { - path.slots[0]++; - continue; - } - ref_item = btrfs_item_ptr(leaf, path.slots[0], - struct btrfs_extent_ref); - ref_root = btrfs_ref_root(leaf, ref_item); - ref_owner = btrfs_ref_objectid(leaf, ref_item); - if ((ref_root == BTRFS_FS_TREE_OBJECTID) && - (ref_owner >= BTRFS_FIRST_FREE_OBJECTID)) { - file_extent = 1; - break; - } + ei = btrfs_item_ptr(leaf, path.slots[0], + struct btrfs_extent_item); + if (!(btrfs_extent_flags(leaf, ei) & BTRFS_EXTENT_FLAG_DATA)) { path.slots[0]++; + goto next; } - if (!file_extent) + + BUG_ON(btrfs_item_size_nr(leaf, path.slots[0]) != sizeof(*ei) + + btrfs_extent_inline_ref_size(BTRFS_EXTENT_DATA_REF_KEY)); + + iref = (struct btrfs_extent_inline_ref *)(ei + 1); + key.type = btrfs_extent_inline_ref_type(leaf, iref); + BUG_ON(key.type != BTRFS_EXTENT_DATA_REF_KEY); + dref = (struct btrfs_extent_data_ref *)(&iref->offset); + if (btrfs_extent_data_ref_root(leaf, dref) != + BTRFS_FS_TREE_OBJECTID) { + path.slots[0]++; goto next; + } if (bytenr > last_byte) { ret = create_image_file_range(trans, root, objectid, @@ -1727,7 +1726,6 @@ static int create_subvol(struct btrfs_trans_handle *trans, ret = btrfs_make_root_dir(trans, new_root, BTRFS_FIRST_FREE_OBJECTID); BUG_ON(ret); - btrfs_free_fs_root(root->fs_info, new_root); return 0; } @@ -1737,6 +1735,7 @@ static int init_btrfs(struct btrfs_root *root) struct btrfs_key location; struct btrfs_trans_handle *trans; struct btrfs_fs_info *fs_info = root->fs_info; + struct extent_buffer *tmp; trans = btrfs_start_transaction(root, 1); BUG_ON(!trans); @@ -1775,6 +1774,11 @@ static int init_btrfs(struct btrfs_root *root) ret = create_subvol(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID); BUG_ON(ret); + ret = __btrfs_cow_block(trans, fs_info->csum_root, + fs_info->csum_root->node, NULL, 0, &tmp, 0, 0); + BUG_ON(ret); + free_extent_buffer(tmp); + ret = btrfs_commit_transaction(trans, root); BUG_ON(ret); err: @@ -1906,7 +1910,7 @@ fail: static int relocate_one_reference(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 extent_start, u64 extent_size, - u64 objectid, struct btrfs_key *leaf_key, + struct btrfs_key *extent_key, struct extent_io_tree *reloc_tree) { struct extent_buffer *leaf; @@ -1916,72 +1920,32 @@ static int relocate_one_reference(struct btrfs_trans_handle *trans, struct btrfs_inode_item inode; struct blk_iterate_data data; u64 bytenr; - u64 offset; u64 num_bytes; u64 cur_offset; u64 new_pos; u64 nbytes; - u64 root_gen; - u64 root_owner; u64 sector_end; - u32 nritems; u32 sectorsize = root->sectorsize; unsigned long ptr; - int found = 0; int datacsum; int fd; int ret; - memcpy(&key, leaf_key, sizeof(key)); - if (key.objectid < objectid || - (key.objectid == objectid && - key.type < BTRFS_EXTENT_DATA_KEY)) { - key.objectid = objectid; - key.type = BTRFS_EXTENT_DATA_KEY; - key.offset = 0; - } btrfs_init_path(&path); -recow: - ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); - if (ret < 0) + ret = btrfs_search_slot(trans, root, extent_key, &path, -1, 1); + if (ret) goto fail; leaf = path.nodes[0]; - nritems = btrfs_header_nritems(leaf); - while (1) { - if (path.slots[0] >= nritems) { - ret = btrfs_next_leaf(root, &path); - if (ret < 0) - goto fail; - if (ret > 0) - break; - btrfs_item_key_to_cpu(path.nodes[0], &key, - path.slots[0]); - btrfs_release_path(root, &path); - goto recow; - } - btrfs_item_key_to_cpu(leaf, &key, path.slots[0]); - if (key.objectid != objectid || - key.type != BTRFS_EXTENT_DATA_KEY) - break; - fi = btrfs_item_ptr(leaf, path.slots[0], - struct btrfs_file_extent_item); - if (extent_start == btrfs_file_extent_disk_bytenr(leaf, fi) && - extent_size == btrfs_file_extent_disk_num_bytes(leaf, fi)) { - offset = key.offset; - found = 1; - break; - } - path.slots[0]++; - } - - if (!found) { + fi = btrfs_item_ptr(leaf, path.slots[0], + struct btrfs_file_extent_item); + BUG_ON(btrfs_file_extent_offset(leaf, fi) > 0); + if (extent_start != btrfs_file_extent_disk_bytenr(leaf, fi) || + extent_size != btrfs_file_extent_disk_num_bytes(leaf, fi)) { ret = 1; goto fail; } - root_gen = btrfs_header_generation(leaf); - root_owner = btrfs_header_owner(leaf); bytenr = extent_start + btrfs_file_extent_offset(leaf, fi); num_bytes = btrfs_file_extent_num_bytes(leaf, fi); @@ -1989,15 +1953,15 @@ recow: if (ret) goto fail; - ret = btrfs_free_extent(trans, root, - extent_start, extent_size, leaf->start, - root_owner, root_gen, objectid, 0); + ret = btrfs_free_extent(trans, root, extent_start, extent_size, 0, + root->root_key.objectid, + extent_key->objectid, extent_key->offset); if (ret) goto fail; btrfs_release_path(root, &path); - key.objectid = objectid; + key.objectid = extent_key->objectid; key.offset = 0; key.type = BTRFS_INODE_ITEM_KEY; ret = btrfs_lookup_inode(trans, root, &path, &key, 0); @@ -2018,8 +1982,8 @@ recow: .trans = trans, .root = root, .inode = &inode, - .objectid = objectid, - .first_block = offset / sectorsize, + .objectid = extent_key->objectid, + .first_block = extent_key->offset / sectorsize, .disk_block = 0, .num_blocks = 0, .boundary = (u64)-1, @@ -2027,7 +1991,7 @@ recow: .errcode = 0, }; - cur_offset = offset; + cur_offset = extent_key->offset; while (num_bytes > 0) { sector_end = bytenr + sectorsize - 1; if (test_range_bit(reloc_tree, bytenr, sector_end, @@ -2040,7 +2004,7 @@ recow: goto fail; new_pos = key.objectid; - if (cur_offset == offset) { + if (cur_offset == extent_key->offset) { fd = root->fs_info->fs_devices->latest_bdev; readahead(fd, bytenr, num_bytes); } @@ -2068,14 +2032,15 @@ recow: } if (data.num_blocks > 0) { - ret = record_file_blocks(trans, root, objectid, &inode, + ret = record_file_blocks(trans, root, + extent_key->objectid, &inode, data.first_block, data.disk_block, data.num_blocks, datacsum); if (ret) goto fail; } - key.objectid = objectid; + key.objectid = extent_key->objectid; key.offset = 0; key.type = BTRFS_INODE_ITEM_KEY; ret = btrfs_lookup_inode(trans, root, &path, &key, 1); @@ -2101,21 +2066,22 @@ static int relocate_extents_range(struct btrfs_root *fs_root, struct btrfs_root *extent_root = info->extent_root; struct btrfs_root *cur_root = NULL; struct btrfs_trans_handle *trans; - struct btrfs_extent_ref *ref_item; + struct btrfs_extent_data_ref *dref; + struct btrfs_extent_inline_ref *iref; + struct btrfs_extent_item *ei; struct extent_buffer *leaf; struct btrfs_key key; - struct btrfs_key leaf_key; + struct btrfs_key extent_key; struct btrfs_path path; struct extent_io_tree reloc_tree; + unsigned long ptr; + unsigned long end; u64 cur_byte; u64 num_bytes; u64 ref_root; - u64 ref_owner; - u64 num_refs; - u64 leaf_start; + u64 num_extents; int pass = 0; int ret; - int found; btrfs_init_path(&path); extent_io_tree_init(&reloc_tree); @@ -2141,7 +2107,7 @@ static int relocate_extents_range(struct btrfs_root *fs_root, btrfs_release_path(extent_root, &path); again: cur_root = (pass % 2 == 0) ? ext2_root : fs_root; - num_refs = 0; + num_extents = 0; trans = btrfs_start_transaction(cur_root, 1); BUG_ON(!trans); @@ -2175,53 +2141,47 @@ next: if (key.objectid >= end_byte) break; + num_extents++; + cur_byte = key.objectid; num_bytes = key.offset; - found = 0; - while (1) { - if (path.slots[0] >= btrfs_header_nritems(leaf)) { - ret = btrfs_next_leaf(extent_root, &path); - if (ret > 0) - break; - if (ret < 0) - goto fail; - leaf = path.nodes[0]; - } + ei = btrfs_item_ptr(leaf, path.slots[0], + struct btrfs_extent_item); + BUG_ON(!(btrfs_extent_flags(leaf, ei) & + BTRFS_EXTENT_FLAG_DATA)); - btrfs_item_key_to_cpu(leaf, &key, path.slots[0]); - if (key.objectid != cur_byte) - break; - if (key.type != BTRFS_EXTENT_REF_KEY) { - path.slots[0]++; - continue; - } - ref_item = btrfs_item_ptr(leaf, path.slots[0], - struct btrfs_extent_ref); - ref_root = btrfs_ref_root(leaf, ref_item); - ref_owner = btrfs_ref_objectid(leaf, ref_item); - leaf_start = key.offset; - num_refs++; - - BUG_ON(ref_owner < BTRFS_FIRST_FREE_OBJECTID); - if (ref_root == cur_root->root_key.objectid) { - found = 1; + ptr = btrfs_item_ptr_offset(leaf, path.slots[0]); + end = ptr + btrfs_item_size_nr(leaf, path.slots[0]); + + ptr += sizeof(struct btrfs_extent_item); + + while (ptr < end) { + iref = (struct btrfs_extent_inline_ref *)ptr; + key.type = btrfs_extent_inline_ref_type(leaf, iref); + BUG_ON(key.type != BTRFS_EXTENT_DATA_REF_KEY); + dref = (struct btrfs_extent_data_ref *)(&iref->offset); + ref_root = btrfs_extent_data_ref_root(leaf, dref); + extent_key.objectid = + btrfs_extent_data_ref_objectid(leaf, dref); + extent_key.offset = + btrfs_extent_data_ref_offset(leaf, dref); + extent_key.type = BTRFS_EXTENT_DATA_KEY; + BUG_ON(btrfs_extent_data_ref_count(leaf, dref) != 1); + + if (ref_root == cur_root->root_key.objectid) break; - } - path.slots[0]++; + + ptr += btrfs_extent_inline_ref_size(key.type); } - if (!found) - goto next; - leaf = read_tree_block(cur_root, leaf_start, - btrfs_level_size(cur_root, 0), 0); - BUG_ON(!leaf); - BUG_ON(btrfs_header_level(leaf) != 0); - btrfs_item_key_to_cpu(leaf, &leaf_key, 0); - free_extent_buffer(leaf); + if (ptr >= end) { + path.slots[0]++; + goto next; + } ret = relocate_one_reference(trans, cur_root, cur_byte, - num_bytes, ref_owner, - &leaf_key, &reloc_tree); + num_bytes, &extent_key, + &reloc_tree); if (ret < 0) goto fail; @@ -2240,10 +2200,10 @@ next: ret = btrfs_commit_transaction(trans, cur_root); BUG_ON(ret); - if (num_refs > 0 && pass++ < 16) + if (num_extents > 0 && pass++ < 16) goto again; - ret = (num_refs > 0) ? -1 : 0; + ret = (num_extents > 0) ? -1 : 0; fail: btrfs_release_path(cur_root, &path); extent_io_tree_cleanup(&reloc_tree); @@ -2477,7 +2437,6 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr) fprintf(stderr, "error during cleanup_sys_chunk %d\n", ret); goto fail; } - btrfs_free_fs_root(ext2_root->fs_info, ext2_root); ret = close_ctree(root); if (ret) { fprintf(stderr, "error during close_ctree %d\n", ret); @@ -2706,7 +2665,6 @@ next_extent: path.slots[0]++; } btrfs_release_path(ext2_root, &path); - btrfs_free_fs_root(ext2_root->fs_info, ext2_root); if (offset < total_bytes) { fprintf(stderr, "unable to build extent mapping\n"); diff --git a/ctree.c b/ctree.c index 2756dbf3..f70e10cc 100644 --- a/ctree.c +++ b/ctree.c @@ -1266,8 +1266,8 @@ again: b = read_node_slot(root, b, slot); } else { p->slots[level] = slot; - if (ins_len > 0 && btrfs_leaf_free_space(root, b) < - sizeof(struct btrfs_item) + ins_len) { + if (ins_len > 0 && + ins_len > btrfs_leaf_free_space(root, b)) { int sret = split_leaf(trans, root, key, p, ins_len, ret == 0); BUG_ON(sret > 0); @@ -1745,7 +1745,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root right = read_node_slot(root, upper, slot + 1); free_space = btrfs_leaf_free_space(root, right); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { free_extent_buffer(right); return 1; } @@ -1758,7 +1758,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root return 1; } free_space = btrfs_leaf_free_space(root, right); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { free_extent_buffer(right); return 1; } @@ -1897,7 +1897,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root left = read_node_slot(root, path->nodes[1], slot - 1); free_space = btrfs_leaf_free_space(root, left); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { free_extent_buffer(left); return 1; } @@ -1912,7 +1912,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root } free_space = btrfs_leaf_free_space(root, left); - if (free_space < data_size + sizeof(struct btrfs_item)) { + if (free_space < data_size) { free_extent_buffer(left); return 1; } @@ -2557,7 +2557,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, if (!root->node) BUG(); - total_size = total_data + (nr - 1) * sizeof(struct btrfs_item); + total_size = total_data + nr * sizeof(struct btrfs_item); ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); if (ret == 0) { return -EEXIST; @@ -2571,8 +2571,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, nritems = btrfs_header_nritems(leaf); data_end = leaf_data_end(root, leaf); - if (btrfs_leaf_free_space(root, leaf) < - sizeof(struct btrfs_item) + total_size) { + if (btrfs_leaf_free_space(root, leaf) < total_size) { btrfs_print_leaf(root, leaf); printk("not enough freespace need %u have %d\n", total_size, btrfs_leaf_free_space(root, leaf)); diff --git a/disk-io.c b/disk-io.c index 2b5771cb..addebe19 100644 --- a/disk-io.c +++ b/disk-io.c @@ -755,6 +755,8 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, BUG_ON(ret); find_and_setup_log_root(tree_root, fs_info, disk_super); + + fs_info->generation = generation + 1; btrfs_read_block_groups(fs_info->tree_root); key.objectid = BTRFS_FS_TREE_OBJECTID; @@ -771,6 +773,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr) { + u8 fsid[BTRFS_FSID_SIZE]; struct btrfs_super_block buf; int i; int ret; @@ -802,6 +805,11 @@ int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr) sizeof(buf.magic))) continue; + if (i == 0) + memcpy(fsid, buf.fsid, sizeof(fsid)); + else if (memcmp(fsid, buf.fsid, sizeof(fsid))) + continue; + if (btrfs_super_generation(&buf) > transid) { memcpy(sb, &buf, sizeof(*sb)); transid = btrfs_super_generation(&buf); diff --git a/extent-tree.c b/extent-tree.c index bc2fd616..6bc1cc80 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -2071,8 +2071,8 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_key key; struct btrfs_path *path; - struct btrfs_fs_info *info = root->fs_info; - struct btrfs_root *extent_root = info->extent_root; + struct btrfs_extent_ops *ops = root->fs_info->extent_ops; + struct btrfs_root *extent_root = root->fs_info->extent_root; struct extent_buffer *leaf; struct btrfs_extent_item *ei; struct btrfs_extent_inline_ref *iref; @@ -2218,6 +2218,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, } } else { int mark_free = 0; + int pin = 1; if (found_extent) { BUG_ON(is_data && refs_to_drop != @@ -2231,10 +2232,21 @@ static int __free_extent(struct btrfs_trans_handle *trans, } } - ret = pin_down_bytes(trans, root, bytenr, num_bytes, is_data); - if (ret > 0) - mark_free = 1; - BUG_ON(ret < 0); + if (ops && ops->free_extent) { + ret = ops->free_extent(root, bytenr, num_bytes); + if (ret > 0) { + pin = 0; + mark_free = 0; + } + } + + if (pin) { + ret = pin_down_bytes(trans, root, bytenr, num_bytes, + is_data); + if (ret > 0) + mark_free = 1; + BUG_ON(ret < 0); + } ret = btrfs_del_items(trans, extent_root, path, path->slots[0], num_to_del); -- 2.11.4.GIT