Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
btrfsprogs.356
2005-btrfs-convert-add-context-and-operations-s...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 2005-btrfs-convert-add-context-and-operations-struct-to-a.patch of Package btrfsprogs.356
From d931f3d86726b44f9d873f6ca40f1dfb21aa5148 Mon Sep 17 00:00:00 2001 From: Jeff Mahoney <jeffm@suse.com> Date: Wed, 14 Aug 2013 14:39:21 -0400 Subject: [PATCH 06/10] btrfs-convert: add context and operations struct to allow different file systems Push out common convert operations into function pointers that we can ultimately allow other file systems to use to provide their own conversions. Signed-off-by: Jeff Mahoney <jeffm@suse.com> --- btrfs-convert.c | 225 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 172 insertions(+), 53 deletions(-) Index: btrfs-progs-v3.16/btrfs-convert.c =================================================================== --- btrfs-progs-v3.16.orig/btrfs-convert.c +++ btrfs-progs-v3.16/btrfs-convert.c @@ -38,6 +38,7 @@ #include "transaction.h" #include "crc32c.h" #include "utils.h" +#include "bitops.h" #include <ext2fs/ext2_fs.h> #include <ext2fs/ext2fs.h> #include <ext2fs/ext2_ext_attr.h> @@ -45,11 +46,66 @@ #define INO_OFFSET (BTRFS_FIRST_FREE_OBJECTID - EXT2_ROOT_INO) #define CONV_IMAGE_SUBVOL_OBJECTID BTRFS_FIRST_FREE_OBJECTID +struct btrfs_convert_context; +struct btrfs_convert_operations { + const char *name; + int (*open_fs)(struct btrfs_convert_context *cxt, const char *devname); + int (*alloc_block)(struct btrfs_convert_context *cxt, u64 goal, + u64 *block_ret); + int (*test_block)(struct btrfs_convert_context *cxt, u64 block); + void (*free_block)(struct btrfs_convert_context *cxt, u64 block); + int (*copy_inodes)(struct btrfs_convert_context *cxt, + struct btrfs_root *root, int datacsum, + int packing, int noxattr); + void (*close_fs)(struct btrfs_convert_context *cxt); +}; + +struct btrfs_convert_context { + u32 blocksize; + u32 first_data_block; + u32 block_count; + char *volume_name; + struct btrfs_convert_operations *convert_ops; + void *fs_data; +}; + +static inline int convert_alloc_block(struct btrfs_convert_context *cxt, + u64 goal, u64 *ret) +{ + return cxt->convert_ops->alloc_block(cxt, goal, ret); +} + +static inline int convert_test_block(struct btrfs_convert_context *cxt, + u64 block) +{ + return cxt->convert_ops->test_block(cxt, block); +} + +static inline void convert_free_block(struct btrfs_convert_context *cxt, + u64 block) +{ + cxt->convert_ops->free_block(cxt, block); +} + +static inline int copy_inodes(struct btrfs_convert_context *cxt, + struct btrfs_root *root, int datacsum, + int packing, int noxattr) +{ + return cxt->convert_ops->copy_inodes(cxt, root, datacsum, packing, + noxattr); +} + + +static inline void convert_close_fs(struct btrfs_convert_context *cxt) +{ + cxt->convert_ops->close_fs(cxt); +} + /* * Open Ext2fs in readonly mode, read block allocation bitmap and * inode bitmap into memory. */ -static int open_ext2fs(const char *name, ext2_filsys *ret_fs) +static int ext2_open_fs(struct btrfs_convert_context *cxt, const char *name) { errcode_t ret; ext2_filsys ext2_fs; @@ -82,20 +138,33 @@ static int open_ext2fs(const char *name, ino += EXT2_INODES_PER_GROUP(ext2_fs->super); } - *ret_fs = ext2_fs; + if (!(ext2_fs->super->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE)) { + fprintf(stderr, "filetype feature is missing\n"); + goto fail; + } + + cxt->fs_data = ext2_fs; + cxt->blocksize = ext2_fs->blocksize; + cxt->block_count = ext2_fs->super->s_blocks_count; + cxt->volume_name = strndup(ext2_fs->super->s_volume_name, 16); + cxt->first_data_block = ext2_fs->super->s_first_data_block; return 0; fail: return -1; } -static int close_ext2fs(ext2_filsys fs) +static void ext2_close_fs(struct btrfs_convert_context *cxt) { - ext2fs_close(fs); - return 0; + if (cxt->volume_name) + free(cxt->volume_name); + ext2fs_close(cxt->fs_data); } -static int ext2_alloc_block(ext2_filsys fs, u64 goal, u64 *block_ret) +static int ext2_alloc_block(struct btrfs_convert_context *cxt, + u64 goal, u64 *block_ret) { + ext2_filsys fs = cxt->fs_data; blk_t block; if (!ext2fs_new_block(fs, goal, NULL, &block)) { @@ -106,24 +175,25 @@ static int ext2_alloc_block(ext2_filsys return -ENOSPC; } -static int ext2_free_block(ext2_filsys fs, u64 block) +static void ext2_free_block(struct btrfs_convert_context *cxt, u64 block) { + ext2_filsys fs = cxt->fs_data; BUG_ON(block != (blk_t)block); ext2fs_fast_unmark_block_bitmap(fs->block_map, block); - return 0; } -static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs) +static int cache_free_extents(struct btrfs_root *root, + struct btrfs_convert_context *cxt) { int i, ret = 0; blk_t block; u64 bytenr; - u64 blocksize = ext2_fs->blocksize; + u64 blocksize = cxt->blocksize; - block = ext2_fs->super->s_first_data_block; - for (; block < ext2_fs->super->s_blocks_count; block++) { - if (ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block)) + block = cxt->first_data_block; + for (; block < cxt->block_count; block++) { + if (convert_test_block(cxt, block)) continue; bytenr = block * blocksize; ret = set_extent_dirty(&root->fs_info->free_space_cache, @@ -134,7 +204,7 @@ static int cache_free_extents(struct btr for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { bytenr = btrfs_sb_offset(i); bytenr &= ~((u64)BTRFS_STRIPE_LEN - 1); - if (bytenr >= blocksize * ext2_fs->super->s_blocks_count) + if (bytenr >= blocksize * cxt->block_count) break; clear_extent_dirty(&root->fs_info->free_space_cache, bytenr, bytenr + BTRFS_STRIPE_LEN - 1, 0); @@ -1034,9 +1104,11 @@ 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) +static int ext2_copy_inodes(struct btrfs_convert_context *cxt, + struct btrfs_root *root, + int datacsum, int packing, int noxattr) { + ext2_filsys ext2_fs = cxt->fs_data; int ret; errcode_t err; ext2_inode_scan ext2_scan; @@ -1086,6 +1158,14 @@ static int copy_inodes(struct btrfs_root return ret; } +static int +ext2_test_block(struct btrfs_convert_context *cxt, u64 block) +{ + ext2_filsys ext2_fs = cxt->fs_data; + BUG_ON(block != (u32)block); + return ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block); +} + /* * Construct a range of ext2fs image file. * scan block allocation bitmap, find all blocks used by the ext2fs @@ -1098,9 +1178,9 @@ static int create_image_file_range(struc struct btrfs_root *root, u64 objectid, struct btrfs_inode_item *inode, u64 start_byte, u64 end_byte, - ext2_filsys ext2_fs) + struct btrfs_convert_context *cxt) { - u32 blocksize = ext2_fs->blocksize; + u32 blocksize = cxt->blocksize; u32 block = start_byte / blocksize; u32 last_block = (end_byte + blocksize - 1) / blocksize; int ret = 0; @@ -1110,7 +1190,7 @@ static int create_image_file_range(struc data.first_block = block; for (; start_byte < end_byte; block++, start_byte += blocksize) { - if (!ext2fs_fast_test_block_bitmap(ext2_fs->block_map, block)) + if (!convert_test_block(cxt, block)) continue; ret = block_iterate_proc(block, block, &data); if (ret & BLOCK_ABORT) { @@ -1135,10 +1215,10 @@ fail: return ret; } /* - * Create the ext2fs image file. + * Create the fs image file. */ -static int create_ext2_image(struct btrfs_root *root, ext2_filsys ext2_fs, - const char *name) +static int create_image(struct btrfs_convert_context *cxt, + struct btrfs_root *root, const char *name) { int ret; struct btrfs_key key; @@ -1251,7 +1331,7 @@ next: if (bytenr > last_byte) { ret = create_image_file_range(trans, root, objectid, &btrfs_inode, last_byte, - bytenr, ext2_fs); + bytenr, cxt); if (ret) goto fail; } @@ -1274,7 +1354,7 @@ next: if (total_bytes > last_byte) { ret = create_image_file_range(trans, root, objectid, &btrfs_inode, last_byte, - total_bytes, ext2_fs); + total_bytes, cxt); if (ret) goto fail; } @@ -1613,7 +1693,7 @@ static int init_btrfs(struct btrfs_root btrfs_set_root_dirid(&fs_info->fs_root->root_item, BTRFS_FIRST_FREE_OBJECTID); - /* subvol for ext2 image file */ + /* subvol for fs image file */ ret = create_subvol(trans, root, CONV_IMAGE_SUBVOL_OBJECTID); BUG_ON(ret); /* subvol for data relocation */ @@ -2175,6 +2255,39 @@ err: return ret; } +static struct btrfs_convert_operations ext2_convert_ops = { + .name = "ext2", + .open_fs = ext2_open_fs, + .alloc_block = ext2_alloc_block, + .copy_inodes = ext2_copy_inodes, + .test_block = ext2_test_block, + .free_block = ext2_free_block, + .close_fs = ext2_close_fs, +}; + +static struct btrfs_convert_operations *convert_operations[] = { + &ext2_convert_ops, +}; + +static int convert_open_fs(const char *devname, + struct btrfs_convert_context *cxt) +{ + int i; + + memset(cxt, 0, sizeof(*cxt)); + + for (i = 0; i < ARRAY_SIZE(convert_operations); i++) { + int ret = convert_operations[i]->open_fs(cxt, devname); + if (ret == 0) { + cxt->convert_ops = convert_operations[i]; + return ret; + } + } + + fprintf(stderr, "No file system found to convert.\n"); + return -1; +} + static int do_convert(const char *devname, int datacsum, int packing, int noxattr, int copylabel, const char *fslabel) { @@ -2184,28 +2297,23 @@ static int do_convert(const char *devnam u64 blocks[7]; u64 total_bytes; u64 super_bytenr; - ext2_filsys ext2_fs; struct btrfs_root *root; struct btrfs_root *image_root; + struct btrfs_convert_context cxt; + char *subvol_name = NULL; - ret = open_ext2fs(devname, &ext2_fs); - if (ret) { - fprintf(stderr, "unable to open the Ext2fs\n"); + ret = convert_open_fs(devname, &cxt); + if (ret) goto fail; - } - blocksize = ext2_fs->blocksize; - total_bytes = (u64)ext2_fs->super->s_blocks_count * blocksize; + + blocksize = cxt.blocksize; + total_bytes = (u64)blocksize * (u64)cxt.block_count; 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; - } for (i = 0; i < 7; i++) { - ret = ext2_alloc_block(ext2_fs, 0, blocks + i); + ret = convert_alloc_block(&cxt, 0, blocks + i); if (ret) { fprintf(stderr, "not enough free space\n"); goto fail; @@ -2218,7 +2326,7 @@ static int do_convert(const char *devnam fprintf(stderr, "unable to open %s\n", devname); goto fail; } - ret = make_btrfs(fd, devname, ext2_fs->super->s_volume_name, + ret = make_btrfs(fd, devname, cxt.volume_name, NULL, blocks, total_bytes, blocksize, blocksize, blocksize, blocksize, 0); if (ret) { @@ -2237,7 +2345,7 @@ static int do_convert(const char *devnam fprintf(stderr, "unable to open ctree\n"); goto fail; } - ret = cache_free_extents(root, ext2_fs); + ret = cache_free_extents(root, &cxt); if (ret) { fprintf(stderr, "error during cache_free_extents %d\n", ret); goto fail; @@ -2246,7 +2354,7 @@ static int do_convert(const char *devnam /* recover block allocation bitmap */ for (i = 0; i < 7; i++) { blocks[i] /= blocksize; - ext2_free_block(ext2_fs, blocks[i]); + convert_free_block(&cxt, blocks[i]); } ret = init_btrfs(root); if (ret) { @@ -2254,31 +2362,43 @@ static int do_convert(const char *devnam goto fail; } printf("creating btrfs metadata.\n"); - ret = copy_inodes(root, ext2_fs, datacsum, packing, noxattr); + ret = copy_inodes(&cxt, root, datacsum, packing, noxattr); if (ret) { fprintf(stderr, "error during copy_inodes %d\n", ret); goto fail; } - printf("creating ext2fs image file.\n"); - image_root = link_subvol(root, "ext2_saved", + + printf("creating %s image file.\n", cxt.convert_ops->name); + ret = asprintf(&subvol_name, "%s_saved", cxt.convert_ops->name); + if (ret < 0) { + fprintf(stderr, "error allocating subvolume name: %s_saved\n", + cxt.convert_ops->name); + goto fail; + } + + image_root = link_subvol(root, subvol_name, CONV_IMAGE_SUBVOL_OBJECTID); + + free(subvol_name); + if (!image_root) { fprintf(stderr, "unable to create subvol\n"); goto fail; } - ret = create_ext2_image(image_root, ext2_fs, "image"); + ret = create_image(&cxt, image_root, "image"); if (ret) { - fprintf(stderr, "error during create_ext2_image %d\n", ret); + fprintf(stderr, "error during create_image %d\n", ret); goto fail; } 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); + cxt.volume_name, BTRFS_LABEL_SIZE); 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); + strncpy(root->fs_info->super_copy->label, fslabel, + BTRFS_LABEL_SIZE); fprintf(stderr, "set label to '%s'\n", fslabel); } @@ -2293,11 +2413,11 @@ static int do_convert(const char *devnam fprintf(stderr, "error during close_ctree %d\n", ret); goto fail; } - close_ext2fs(ext2_fs); + convert_close_fs(&cxt); /* * If this step succeed, we get a mountable btrfs. Otherwise - * the ext2fs is left unchanged. + * the source fs is left unchanged. */ ret = migrate_super_block(fd, super_bytenr, blocksize); if (ret) { @@ -2680,7 +2800,7 @@ static void print_usage(void) printf("\t-d disable data checksum\n"); printf("\t-i ignore xattrs and ACLs\n"); printf("\t-n disable packing of small files\n"); - printf("\t-r roll back to ext2fs\n"); + printf("\t-r roll back to source fs\n"); printf("\t-l LABEL set filesystem label\n"); printf("\t-L use label from converted fs\n"); }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor