#include <ext2fs/ext2_ext_attr.h>
#define INO_OFFSET (BTRFS_FIRST_FREE_OBJECTID - EXT2_ROOT_INO)
-#define EXT2_IMAGE_SUBVOL_OBJECTID BTRFS_FIRST_FREE_OBJECTID
+#define CONV_IMAGE_SUBVOL_OBJECTID BTRFS_FIRST_FREE_OBJECTID
struct task_ctx {
uint32_t max_copy_inodes;
static int after_copied_inodes(void *p)
{
- struct task_ctx *priv = p;
-
printf("\n");
- task_period_stop(priv->info);
+ fflush(stdout);
return 0;
}
}
static int custom_alloc_extent(struct btrfs_root *root, u64 num_bytes,
- u64 hint_byte, struct btrfs_key *ins)
+ u64 hint_byte, struct btrfs_key *ins,
+ int metadata)
{
u64 start;
u64 end;
continue;
}
+ if (metadata) {
+ BUG_ON(num_bytes != root->nodesize);
+ if (check_crossing_stripes(start, num_bytes)) {
+ last = round_down(start + num_bytes,
+ BTRFS_STRIPE_LEN);
+ continue;
+ }
+ }
clear_extent_dirty(&root->fs_info->free_space_cache,
start, start + num_bytes - 1, 0);
.free_extent = custom_free_extent,
};
+static int convert_insert_dirent(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ const char *name, size_t name_len,
+ u64 dir, u64 objectid,
+ u8 file_type, u64 index_cnt,
+ struct btrfs_inode_item *inode)
+{
+ int ret;
+ u64 inode_size;
+ struct btrfs_key location = {
+ .objectid = objectid,
+ .offset = 0,
+ .type = BTRFS_INODE_ITEM_KEY,
+ };
+
+ ret = btrfs_insert_dir_item(trans, root, name, name_len,
+ dir, &location, file_type, index_cnt);
+ if (ret)
+ return ret;
+ ret = btrfs_insert_inode_ref(trans, root, name, name_len,
+ objectid, dir, index_cnt);
+ if (ret)
+ return ret;
+ inode_size = btrfs_stack_inode_size(inode) + name_len * 2;
+ btrfs_set_stack_inode_size(inode, inode_size);
+
+ return 0;
+}
+
struct dir_iterate_data {
struct btrfs_trans_handle *trans;
struct btrfs_root *root;
int ret;
int file_type;
u64 objectid;
- u64 inode_size;
char dotdot[] = "..";
- struct btrfs_key location;
struct dir_iterate_data *idata = (struct dir_iterate_data *)priv_data;
int name_len;
if (dirent->inode < EXT2_GOOD_OLD_FIRST_INO)
return 0;
- location.objectid = objectid;
- location.offset = 0;
- btrfs_set_key_type(&location, BTRFS_INODE_ITEM_KEY);
-
file_type = dirent->name_len >> 8;
BUG_ON(file_type > EXT2_FT_SYMLINK);
- ret = btrfs_insert_dir_item(idata->trans, idata->root,
- dirent->name, name_len,
- idata->objectid, &location,
+
+ ret = convert_insert_dirent(idata->trans, idata->root, dirent->name,
+ name_len, idata->objectid, objectid,
filetype_conversion_table[file_type],
- idata->index_cnt);
- if (ret)
- goto fail;
- ret = btrfs_insert_inode_ref(idata->trans, idata->root,
- dirent->name, name_len,
- objectid, idata->objectid,
- idata->index_cnt);
- if (ret)
- goto fail;
+ idata->index_cnt, idata->inode);
+ if (ret < 0) {
+ idata->errcode = ret;
+ return BLOCK_ABORT;
+ }
+
idata->index_cnt++;
- inode_size = btrfs_stack_inode_size(idata->inode) +
- name_len * 2;
- btrfs_set_stack_inode_size(idata->inode, inode_size);
return 0;
-fail:
- idata->errcode = ret;
- return BLOCK_ABORT;
}
static int create_dir_entries(struct btrfs_trans_handle *trans,
num_bytes);
}
-static int block_iterate_proc(ext2_filsys ext2_fs,
- u64 disk_block, u64 file_block,
+static int block_iterate_proc(u64 disk_block, u64 file_block,
struct blk_iterate_data *idata)
{
- int ret;
+ int ret = 0;
int sb_region;
int do_barrier;
struct btrfs_root *root = idata->root;
idata->boundary = bytenr / root->sectorsize;
}
idata->num_blocks++;
- return 0;
fail:
- idata->errcode = ret;
- return BLOCK_ABORT;
+ return ret;
}
static int __block_iterate_proc(ext2_filsys fs, blk_t *blocknr,
e2_blkcnt_t blockcnt, blk_t ref_block,
int ref_offset, void *priv_data)
{
+ int ret;
struct blk_iterate_data *idata;
idata = (struct blk_iterate_data *)priv_data;
- return block_iterate_proc(fs, *blocknr, blockcnt, idata);
+ ret = block_iterate_proc(*blocknr, blockcnt, idata);
+ if (ret) {
+ idata->errcode = ret;
+ return BLOCK_ABORT;
+ }
+ return 0;
}
/*
struct ext2_inode *src, u32 blocksize)
{
btrfs_set_stack_inode_generation(dst, 1);
+ btrfs_set_stack_inode_sequence(dst, 0);
+ btrfs_set_stack_inode_transid(dst, 1);
btrfs_set_stack_inode_size(dst, src->i_size);
btrfs_set_stack_inode_nbytes(dst, 0);
btrfs_set_stack_inode_block_group(dst, 0);
new_decode_dev(src->i_block[1]));
}
}
+ memset(&dst->reserved, 0, sizeof(dst->reserved));
+
return 0;
}
int datacsum, int packing, int noxattr)
{
int ret;
- struct btrfs_key inode_key;
struct btrfs_inode_item btrfs_inode;
if (ext2_inode->i_links_count == 0)
if (ret)
return ret;
}
- inode_key.objectid = objectid;
- inode_key.offset = 0;
- btrfs_set_key_type(&inode_key, BTRFS_INODE_ITEM_KEY);
- ret = btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
- return ret;
+ return btrfs_insert_inode(trans, root, objectid, &btrfs_inode);
}
static int copy_disk_extent(struct btrfs_root *root, u64 dst_bytenr,
}
ret = btrfs_commit_transaction(trans, root);
BUG_ON(ret);
+ ext2fs_close_inode_scan(ext2_scan);
return ret;
}
for (; start_byte < end_byte; block++, start_byte += blocksize) {
if (!ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block))
continue;
- ret = block_iterate_proc(NULL, block, block, &data);
- if (ret & BLOCK_ABORT) {
- ret = data.errcode;
+ ret = block_iterate_proc(block, block, &data);
+ if (ret < 0)
goto fail;
- }
}
if (data.num_blocks > 0) {
ret = record_file_blocks(&data, data.first_block,
* special, we can't rely on relocate_extents_range to relocate it.
*/
for (last_byte = 0; last_byte < first_free; last_byte += sectorsize) {
- ret = custom_alloc_extent(root, sectorsize, 0, &key);
+ ret = custom_alloc_extent(root, sectorsize, 0, &key, 0);
if (ret)
goto fail;
ret = copy_disk_extent(root, key.objectid, last_byte,
btrfs_set_key_type(&location, BTRFS_INODE_ITEM_KEY);
ret = btrfs_insert_dir_item(trans, root, name, strlen(name),
btrfs_root_dirid(&root->root_item),
- &location, EXT2_FT_REG_FILE, objectid);
+ &location, BTRFS_FT_REG_FILE, objectid);
if (ret)
goto fail;
ret = btrfs_insert_inode_ref(trans, root, name, strlen(name),
BTRFS_FIRST_FREE_OBJECTID);
/* subvol for ext2 image file */
- ret = create_subvol(trans, root, EXT2_IMAGE_SUBVOL_OBJECTID);
+ ret = create_subvol(trans, root, CONV_IMAGE_SUBVOL_OBJECTID);
BUG_ON(ret);
/* subvol for data relocation */
ret = create_subvol(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
ret = get_state_private(reloc_tree, bytenr, &new_pos);
BUG_ON(ret);
} else {
- ret = custom_alloc_extent(root, sectorsize, 0, &key);
+ ret = custom_alloc_extent(root, sectorsize, 0, &key, 0);
if (ret)
goto fail;
new_pos = key.objectid;
BUG_ON(ret);
}
- ret = block_iterate_proc(NULL, new_pos / sectorsize,
+ ret = block_iterate_proc(new_pos / sectorsize,
cur_offset / sectorsize, &data);
- if (ret & BLOCK_ABORT) {
- ret = data.errcode;
+ if (ret < 0)
goto fail;
- }
cur_offset += sectorsize;
bytenr += sectorsize;
}
static int relocate_extents_range(struct btrfs_root *fs_root,
- struct btrfs_root *ext2_root,
+ struct btrfs_root *image_root,
u64 start_byte, u64 end_byte)
{
struct btrfs_fs_info *info = fs_root->fs_info;
}
btrfs_release_path(&path);
again:
- cur_root = (pass % 2 == 0) ? ext2_root : fs_root;
+ cur_root = (pass % 2 == 0) ? image_root : fs_root;
num_extents = 0;
trans = btrfs_start_transaction(cur_root, 1);
* relocate data in system chunk
*/
static int cleanup_sys_chunk(struct btrfs_root *fs_root,
- struct btrfs_root *ext2_root)
+ struct btrfs_root *image_root)
{
struct btrfs_block_group_cache *cache;
int i, ret = 0;
end_byte = cache->key.objectid + cache->key.offset;
if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) {
- ret = relocate_extents_range(fs_root, ext2_root,
+ ret = relocate_extents_range(fs_root, image_root,
cache->key.objectid,
end_byte);
if (ret)
offset = btrfs_sb_offset(i);
offset &= ~((u64)BTRFS_STRIPE_LEN - 1);
- ret = relocate_extents_range(fs_root, ext2_root,
+ ret = relocate_extents_range(fs_root, image_root,
offset, offset + BTRFS_STRIPE_LEN);
if (ret)
goto fail;
u64 super_bytenr;
ext2_filsys ext2_fs;
struct btrfs_root *root;
- struct btrfs_root *ext2_root;
+ struct btrfs_root *image_root;
struct task_ctx ctx;
char features_buf[64];
+ struct btrfs_mkfs_config mkfs_cfg;
ret = open_ext2fs(devname, &ext2_fs);
if (ret) {
fprintf(stderr, "filetype feature is missing\n");
goto fail;
}
- if (btrfs_check_nodesize(nodesize, blocksize))
+ if (btrfs_check_nodesize(nodesize, blocksize, features))
goto fail;
blocks_per_node = nodesize / blocksize;
ret = -blocks_per_node;
printf("\tblocksize: %u\n", blocksize);
printf("\tnodesize: %u\n", nodesize);
printf("\tfeatures: %s\n", features_buf);
- ret = make_btrfs(fd, devname, ext2_fs->super->s_volume_name,
- NULL, blocks, total_bytes, nodesize,
- blocksize, blocksize, features);
+
+ mkfs_cfg.label = ext2_fs->super->s_volume_name;
+ mkfs_cfg.fs_uuid = NULL;
+ memcpy(mkfs_cfg.blocks, blocks, sizeof(blocks));
+ mkfs_cfg.num_bytes = total_bytes;
+ mkfs_cfg.nodesize = nodesize;
+ mkfs_cfg.sectorsize = blocksize;
+ mkfs_cfg.stripesize = blocksize;
+ mkfs_cfg.features = features;
+
+ ret = make_btrfs(fd, &mkfs_cfg);
if (ret) {
fprintf(stderr, "unable to create initial ctree: %s\n",
strerror(-ret));
task_deinit(ctx.info);
}
printf("creating ext2fs image file.\n");
- ext2_root = link_subvol(root, "ext2_saved", EXT2_IMAGE_SUBVOL_OBJECTID);
- if (!ext2_root) {
+ image_root = link_subvol(root, "ext2_saved", CONV_IMAGE_SUBVOL_OBJECTID);
+ if (!image_root) {
fprintf(stderr, "unable to create subvol\n");
goto fail;
}
- ret = create_ext2_image(ext2_root, ext2_fs, "image", datacsum);
+ ret = create_ext2_image(image_root, ext2_fs, "image", datacsum);
if (ret) {
fprintf(stderr, "error during create_ext2_image %d\n", ret);
goto fail;
fprintf(stderr, "copy label '%s'\n",
root->fs_info->super_copy->label);
} else if (copylabel == -1) {
- strncpy(root->fs_info->super_copy->label, fslabel, BTRFS_LABEL_SIZE);
+ strcpy(root->fs_info->super_copy->label, fslabel);
fprintf(stderr, "set label to '%s'\n", fslabel);
}
printf("cleaning up system chunk.\n");
- ret = cleanup_sys_chunk(root, ext2_root);
+ ret = cleanup_sys_chunk(root, image_root);
if (ret) {
fprintf(stderr, "error during cleanup_sys_chunk %d\n", ret);
goto fail;
int ret;
int i;
struct btrfs_root *root;
- struct btrfs_root *ext2_root;
+ struct btrfs_root *image_root;
struct btrfs_root *chunk_root;
struct btrfs_dir_item *dir;
struct btrfs_inode_item *inode;
btrfs_init_path(&path);
- key.objectid = EXT2_IMAGE_SUBVOL_OBJECTID;
+ key.objectid = CONV_IMAGE_SUBVOL_OBJECTID;
key.type = BTRFS_ROOT_ITEM_KEY;
key.offset = (u64)-1;
- ext2_root = btrfs_read_fs_root(root->fs_info, &key);
- if (!ext2_root || IS_ERR(ext2_root)) {
+ image_root = btrfs_read_fs_root(root->fs_info, &key);
+ if (!image_root || IS_ERR(image_root)) {
fprintf(stderr, "unable to open subvol %llu\n",
(unsigned long long)key.objectid);
goto fail;
name = "image";
root_dir = btrfs_root_dirid(&root->root_item);
- dir = btrfs_lookup_dir_item(NULL, ext2_root, &path,
+ dir = btrfs_lookup_dir_item(NULL, image_root, &path,
root_dir, name, strlen(name), 0);
if (!dir || IS_ERR(dir)) {
fprintf(stderr, "unable to find file %s\n", name);
objectid = key.objectid;
- ret = btrfs_lookup_inode(NULL, ext2_root, &path, &key, 0);
+ ret = btrfs_lookup_inode(NULL, image_root, &path, &key, 0);
if (ret) {
fprintf(stderr, "unable to find inode item\n");
goto fail;
key.objectid = objectid;
key.offset = 0;
btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
- ret = btrfs_search_slot(NULL, ext2_root, &key, &path, 0, 0);
+ ret = btrfs_search_slot(NULL, image_root, &key, &path, 0, 0);
if (ret != 0) {
fprintf(stderr, "unable to find first file extent\n");
btrfs_release_path(&path);
int usage_error = 0;
int progress = 1;
char *file;
- char *fslabel = NULL;
+ char fslabel[BTRFS_LABEL_SIZE];
u64 features = BTRFS_MKFS_DEFAULT_FEATURES;
while(1) {
{ "label", required_argument, NULL, 'l' },
{ "copy-label", no_argument, NULL, 'L' },
{ "nodesize", required_argument, NULL, 'N' },
+ { "help", no_argument, NULL, GETOPT_VAL_HELP},
{ NULL, 0, NULL, 0 }
};
int c = getopt_long(argc, argv, "dinN:rl:LpO:", long_options, NULL);
break;
case 'l':
copylabel = -1;
- fslabel = strdup(optarg);
- if (strlen(fslabel) > BTRFS_LABEL_SIZE) {
+ if (strlen(optarg) >= BTRFS_LABEL_SIZE) {
fprintf(stderr,
- "warning: label too long, trimmed to %d bytes\n",
- BTRFS_LABEL_SIZE);
- fslabel[BTRFS_LABEL_SIZE] = 0;
+ "WARNING: label too long, trimmed to %d bytes\n",
+ BTRFS_LABEL_SIZE - 1);
}
+ strncpy(fslabel, optarg, BTRFS_LABEL_SIZE - 1);
+ fslabel[BTRFS_LABEL_SIZE - 1] = 0;
break;
case 'L':
copylabel = 1;
case GETOPT_VAL_NO_PROGRESS:
progress = 0;
break;
+ case GETOPT_VAL_HELP:
default:
print_usage();
- return 1;
+ return c != GETOPT_VAL_HELP;
}
}
argc = argc - optind;