From 08f0c73eee929db08431f9ae5c765812358d099d Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Fri, 29 Jan 2016 13:03:29 +0800 Subject: [PATCH] btrfs-progs: Introduce do_convert_v2 function Introduce new function do_convert_v2() to do new convert. Signed-off-by: Qu Wenruo [ use __strncpy_null for label ] Signed-off-by: David Sterba --- btrfs-convert.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 1 deletion(-) diff --git a/btrfs-convert.c b/btrfs-convert.c index 47028d9..d4e3817 100644 --- a/btrfs-convert.c +++ b/btrfs-convert.c @@ -3238,6 +3238,181 @@ static int convert_read_used_space(struct btrfs_convert_context *cctx) return ret; } +static int do_convert_v2(const char *devname, int datacsum, int packing, + int noxattr, u32 nodesize, int copylabel, const char *fslabel, + int progress, u64 features) +{ + int ret; + int fd = -1; + int is_btrfs = 0; + u32 blocksize; + u64 total_bytes; + struct btrfs_root *root; + struct btrfs_root *image_root; + struct btrfs_convert_context cctx; + struct btrfs_key key; + char *subvol_name = NULL; + struct task_ctx ctx; + char features_buf[64]; + struct btrfs_mkfs_config mkfs_cfg; + + init_convert_context(&cctx); + ret = convert_open_fs(devname, &cctx); + if (ret) + goto fail; + ret = convert_read_used_space(&cctx); + if (ret) + goto fail; + + blocksize = cctx.blocksize; + total_bytes = (u64)blocksize * (u64)cctx.block_count; + if (blocksize < 4096) { + fprintf(stderr, "block size is too small\n"); + goto fail; + } + if (btrfs_check_nodesize(nodesize, blocksize, features)) + 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: %u\n", nodesize); + printf("\tfeatures: %s\n", features_buf); + + mkfs_cfg.label = cctx.volume_name; + mkfs_cfg.num_bytes = total_bytes; + mkfs_cfg.nodesize = nodesize; + mkfs_cfg.sectorsize = blocksize; + mkfs_cfg.stripesize = blocksize; + mkfs_cfg.features = features; + /* New convert need these space */ + mkfs_cfg.fs_uuid = malloc(BTRFS_UUID_UNPARSED_SIZE); + mkfs_cfg.chunk_uuid = malloc(BTRFS_UUID_UNPARSED_SIZE); + *(mkfs_cfg.fs_uuid) = '\0'; + *(mkfs_cfg.chunk_uuid) = '\0'; + + ret = make_btrfs(fd, &mkfs_cfg, &cctx); + 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, root, &cctx, datacsum, packing, noxattr); + if (ret) { + fprintf(stderr, "unable to setup the root tree\n"); + goto fail; + } + + printf("creating %s image file.\n", cctx.convert_ops->name); + ret = asprintf(&subvol_name, "%s_saved", cctx.convert_ops->name); + if (ret < 0) { + fprintf(stderr, "error allocating subvolume name: %s_saved\n", + cctx.convert_ops->name); + goto fail; + } + key.objectid = CONV_IMAGE_SUBVOL_OBJECTID; + key.offset = (u64)-1; + key.type = BTRFS_ROOT_ITEM_KEY; + image_root = btrfs_read_fs_root(root->fs_info, &key); + if (!image_root) { + fprintf(stderr, "unable to create subvol\n"); + goto fail; + } + ret = create_image_v2(image_root, &mkfs_cfg, &cctx, fd, + mkfs_cfg.num_bytes, "image", datacsum); + if (ret) { + fprintf(stderr, "error during create_image %d\n", ret); + goto fail; + } + + printf("creating btrfs metadata.\n"); + ctx.max_copy_inodes = (cctx.inodes_count - cctx.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(&cctx, root, datacsum, packing, noxattr, &ctx); + if (ret) { + fprintf(stderr, "error during copy_inodes %d\n", ret); + goto fail; + } + if (progress) { + task_stop(ctx.info); + task_deinit(ctx.info); + } + + image_root = link_subvol(root, subvol_name, CONV_IMAGE_SUBVOL_OBJECTID); + + free(subvol_name); + + memset(root->fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); + if (copylabel == 1) { + __strncpy_null(root->fs_info->super_copy->label, + cctx.volume_name, BTRFS_LABEL_SIZE - 1); + 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; + } + convert_close_fs(&cctx); + clean_convert_context(&cctx); + + /* + * If this step succeed, we get a mountable btrfs. Otherwise + * the source fs 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: + clean_convert_context(&cctx); + if (fd != -1) + close(fd); + if (is_btrfs) + fprintf(stderr, + "WARNING: an error occurred 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) @@ -3985,7 +4160,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) -- 2.7.4