Update converter for the new format

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
master
Yan Zheng 2009-06-03 11:59:47 -04:00 committed by Chris Mason
parent 95d3f20b51
commit 50860d6e31
4 changed files with 145 additions and 168 deletions

264
convert.c
View File

@ -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]++;
}
if (!file_extent)
goto next;
}
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++;
ptr = btrfs_item_ptr_offset(leaf, path.slots[0]);
end = ptr + btrfs_item_size_nr(leaf, path.slots[0]);
BUG_ON(ref_owner < BTRFS_FIRST_FREE_OBJECTID);
if (ref_root == cur_root->root_key.objectid) {
found = 1;
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");

17
ctree.c
View File

@ -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));

View File

@ -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);

View File

@ -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);