Introduce new function do_convert_v2() to do new convert.

Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com>
---
 btrfs-convert.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 utils.c         |   3 +
 2 files changed, 186 insertions(+), 4 deletions(-)

diff --git a/btrfs-convert.c b/btrfs-convert.c
index 9e8158d..8079aea 100644
--- a/btrfs-convert.c
+++ b/btrfs-convert.c
@@ -1217,7 +1217,8 @@ fail:
  * scan ext2's inode bitmap and copy all used inodes.
  */
 static int copy_inodes(struct btrfs_root *root, ext2_filsys ext2_fs,
-                      int datacsum, int packing, int noxattr, struct task_ctx 
*p)
+                      int datacsum, int packing, int noxattr, int skip_root,
+                      struct task_ctx *p)
 {
        int ret;
        errcode_t err;
@@ -1242,7 +1243,7 @@ static int copy_inodes(struct btrfs_root *root, 
ext2_filsys ext2_fs,
                        break;
                /* skip special inode in ext2fs */
                if (ext2_ino < EXT2_GOOD_OLD_FIRST_INO &&
-                   ext2_ino != EXT2_ROOT_INO)
+                   (ext2_ino != EXT2_ROOT_INO || skip_root))
                        continue;
                objectid = ext2_ino + INO_OFFSET;
                ret = copy_single_inode(trans, root,
@@ -2857,6 +2858,183 @@ static int read_ext2_used_space(ext2_filsys fs, struct 
cache_tree *used_tree)
        return ret;
 }
 
+static int do_convert_v2(const char *devname, int datacsum, int packing,
+               int noxattr, u64 nodesize, int copylabel, const char *fslabel,
+               int progress, u64 features)
+{
+       int ret;
+       int fd = -1;
+       int is_btrfs = 0;
+       u32 blocksize;
+       u64 blocks[7];
+       u64 total_bytes;
+       ext2_filsys ext2_fs;
+       struct btrfs_root *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, "unable to open the Ext2fs\n");
+               goto fail;
+       }
+       blocksize = ext2_fs->blocksize;
+       total_bytes = (u64)ext2_fs->super->s_blocks_count * blocksize;
+       if (blocksize < 4096) {
+               fprintf(stderr, "block size is too small\n");
+               goto fail;
+       }
+       if (!(ext2_fs->super->s_feature_incompat &
+             EXT2_FEATURE_INCOMPAT_FILETYPE)) {
+               fprintf(stderr, "filetype feature is missing\n");
+               goto fail;
+       }
+       if (btrfs_check_nodesize(nodesize, blocksize, features))
+               goto fail;
+
+       /* Build the used space tree first */
+       init_mkfs_config(&mkfs_cfg);
+       ret = read_ext2_used_space(ext2_fs, &mkfs_cfg.convert_used);
+       if (ret < 0) {
+               error("fail to read ext2 block bitmap\n");
+               goto fail;
+       }
+
+       fd = open(devname, O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr, "unable to open %s\n", devname);
+               goto fail;
+       }
+       btrfs_parse_features_to_string(features_buf, features);
+       if (features == BTRFS_MKFS_DEFAULT_FEATURES)
+               strcat(features_buf, " (default)");
+
+       printf("create btrfs filesystem:\n");
+       printf("\tblocksize: %u\n", blocksize);
+       printf("\tnodesize:  %llu\n", nodesize);
+       printf("\tfeatures:  %s\n", features_buf);
+
+       mkfs_cfg.label = ext2_fs->super->s_volume_name;
+       mkfs_cfg.fs_uuid = malloc(BTRFS_UUID_UNPARSED_SIZE);
+       if (!mkfs_cfg.fs_uuid) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+       *(mkfs_cfg.fs_uuid) = '\0';
+       mkfs_cfg.chunk_uuid = malloc(BTRFS_UUID_UNPARSED_SIZE);
+       if (!mkfs_cfg.chunk_uuid) {
+               ret = -ENOMEM;
+               goto fail;
+       }
+       *(mkfs_cfg.chunk_uuid) = '\0';
+       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));
+               goto fail;
+       }
+       root = open_ctree_fd(fd, devname, mkfs_cfg.super_bytenr,
+                            OPEN_CTREE_WRITES);
+       if (!root) {
+               fprintf(stderr, "unable to open ctree\n");
+               goto fail;
+       }
+       ret = init_btrfs_v2(&mkfs_cfg, ext2_fs, root, datacsum, packing, 
+                           noxattr);
+       if (ret) {
+               fprintf(stderr, "unable to setup the root tree\n");
+               goto fail;
+       }
+       printf("creating ext2fs image file.\n");
+       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_v2(image_root, &mkfs_cfg, fd, total_bytes,
+                                  "image", datacsum);
+       if (ret) {
+               fprintf(stderr, "error during create_ext2_image %d\n", ret);
+               goto fail;
+       }
+       printf("creating btrfs metadata.\n");
+       ctx.max_copy_inodes = (ext2_fs->super->s_inodes_count
+                       - ext2_fs->super->s_free_inodes_count);
+       ctx.cur_copy_inodes = 0;
+
+       if (progress) {
+               ctx.info = task_init(print_copied_inodes, after_copied_inodes, 
&ctx);
+               task_start(ctx.info);
+       }
+       ret = copy_inodes(root, ext2_fs, datacsum, packing, noxattr, 1, &ctx);
+       if (ret) {
+               fprintf(stderr, "error during copy_inodes %d\n", ret);
+               goto fail;
+       }
+       if (progress) {
+               task_stop(ctx.info);
+               task_deinit(ctx.info);
+       }
+       memset(root->fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE);
+       if (copylabel == 1) {
+               strncpy(root->fs_info->super_copy->label,
+                               ext2_fs->super->s_volume_name, 16);
+               fprintf(stderr, "copy label '%s'\n",
+                               root->fs_info->super_copy->label);
+       } else if (copylabel == -1) {
+               strcpy(root->fs_info->super_copy->label, fslabel);
+               fprintf(stderr, "set label to '%s'\n", fslabel);
+       }
+
+       ret = close_ctree(root);
+       if (ret) {
+               fprintf(stderr, "error during close_ctree %d\n", ret);
+               goto fail;
+       }
+       close_ext2fs(ext2_fs);
+
+       /*
+        * If this step succeed, we get a mountable btrfs. Otherwise
+        * the ext2fs is left unchanged.
+        */
+       ret = migrate_super_block(fd, mkfs_cfg.super_bytenr, blocksize);
+       if (ret) {
+               fprintf(stderr, "unable to migrate super block\n");
+               goto fail;
+       }
+       is_btrfs = 1;
+
+       root = open_ctree_fd(fd, devname, 0, OPEN_CTREE_WRITES);
+       if (!root) {
+               fprintf(stderr, "unable to open ctree\n");
+               goto fail;
+       }
+       close(fd);
+
+       printf("conversion complete.\n");
+       return 0;
+fail:
+       free_mkfs_config(&mkfs_cfg);
+
+       if (fd != -1)
+               close(fd);
+       if (is_btrfs)
+               fprintf(stderr,
+                       "WARNING: an error occured during chunk mapping fixup, 
filesystem mountable but not finalized\n");
+       else
+               fprintf(stderr, "conversion aborted\n");
+       return -1;
+}
+
 static int do_convert(const char *devname, int datacsum, int packing, int 
noxattr,
                u32 nodesize, int copylabel, const char *fslabel, int progress,
                u64 features)
@@ -2933,6 +3111,7 @@ static int do_convert(const char *devname, int datacsum, 
int packing, int noxatt
        printf("\tfeatures:  %s\n", features_buf);
 
        mkfs_cfg.label = ext2_fs->super->s_volume_name;
+       mkfs_cfg.chunk_uuid = NULL;
        mkfs_cfg.fs_uuid = NULL;
        memcpy(mkfs_cfg.blocks, blocks, sizeof(blocks));
        mkfs_cfg.num_bytes = total_bytes;
@@ -2987,7 +3166,7 @@ static int do_convert(const char *devname, int datacsum, 
int packing, int noxatt
                ctx.info = task_init(print_copied_inodes, after_copied_inodes, 
&ctx);
                task_start(ctx.info);
        }
-       ret = copy_inodes(root, ext2_fs, datacsum, packing, noxattr, &ctx);
+       ret = copy_inodes(root, ext2_fs, datacsum, packing, noxattr, 0, &ctx);
        if (ret) {
                fprintf(stderr, "error during copy_inodes %d\n", ret);
                goto fail;
@@ -3606,7 +3785,7 @@ int main(int argc, char *argv[])
        if (rollback) {
                ret = do_rollback(file);
        } else {
-               ret = do_convert(file, datacsum, packing, noxattr, nodesize,
+               ret = do_convert_v2(file, datacsum, packing, noxattr, nodesize,
                                copylabel, fslabel, progress, features);
        }
        if (ret)
diff --git a/utils.c b/utils.c
index f5fadb1..6c5b17a 100644
--- a/utils.c
+++ b/utils.c
@@ -1214,6 +1214,9 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
                                 BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA);
        u64 num_bytes;
 
+       if (!cache_tree_empty(&cfg->convert_used))
+               return make_btrfs_v2(fd, cfg);
+
        buf = malloc(sizeof(*buf) + max(cfg->sectorsize, cfg->nodesize));
        if (!buf)
                return -ENOMEM;
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to