X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=btrfs-convert.c;h=4b4cea42672be507c8d8cbb6410e9d933cc31b61;hb=776cd164b73092ec559a47080ff44aa22bad97a1;hp=727bfea156f26f0c5d20bb8317b2037f1d9e3d5c;hpb=890f4a61d7f4563af24617e7b2a5002cb2bf04cf;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/btrfs-convert.c b/btrfs-convert.c index 727bfea..4b4cea4 100644 --- a/btrfs-convert.c +++ b/btrfs-convert.c @@ -103,6 +103,7 @@ struct btrfs_convert_operations { struct btrfs_root *root, int datacsum, int packing, int noxattr, struct task_ctx *p); void (*close_fs)(struct btrfs_convert_context *cctx); + int (*check_state)(struct btrfs_convert_context *cctx); }; static void init_convert_context(struct btrfs_convert_context *cctx) @@ -132,6 +133,11 @@ static inline void convert_close_fs(struct btrfs_convert_context *cctx) cctx->convert_ops->close_fs(cctx); } +static inline int convert_check_state(struct btrfs_convert_context *cctx) +{ + return cctx->convert_ops->check_state(cctx); +} + static int intersect_with_sb(u64 bytenr, u64 num_bytes) { int i; @@ -277,7 +283,7 @@ static int record_file_blocks(struct blk_iterate_data *data, int ret = 0; struct btrfs_root *root = data->root; struct btrfs_root *convert_root = data->convert_root; - struct btrfs_path *path; + struct btrfs_path path; u64 file_pos = file_block * root->sectorsize; u64 old_disk_bytenr = disk_block * root->sectorsize; u64 num_bytes = num_blocks * root->sectorsize; @@ -289,9 +295,7 @@ static int record_file_blocks(struct blk_iterate_data *data, data->objectid, data->inode, file_pos, 0, num_bytes); - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; + btrfs_init_path(&path); /* * Search real disk bytenr from convert root @@ -310,11 +314,11 @@ static int record_file_blocks(struct blk_iterate_data *data, key.type = BTRFS_EXTENT_DATA_KEY; key.offset = cur_off; - ret = btrfs_search_slot(NULL, convert_root, &key, path, 0, 0); + ret = btrfs_search_slot(NULL, convert_root, &key, &path, 0, 0); if (ret < 0) break; if (ret > 0) { - ret = btrfs_previous_item(convert_root, path, + ret = btrfs_previous_item(convert_root, &path, data->convert_ino, BTRFS_EXTENT_DATA_KEY); if (ret < 0) @@ -324,8 +328,8 @@ static int record_file_blocks(struct blk_iterate_data *data, break; } } - node = path->nodes[0]; - slot = path->slots[0]; + node = path.nodes[0]; + slot = path.slots[0]; btrfs_item_key_to_cpu(node, &key, slot); BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY || key.objectid != data->convert_ino || @@ -334,7 +338,7 @@ static int record_file_blocks(struct blk_iterate_data *data, extent_disk_bytenr = btrfs_file_extent_disk_bytenr(node, fi); extent_num_bytes = btrfs_file_extent_disk_num_bytes(node, fi); BUG_ON(cur_off - key.offset >= extent_num_bytes); - btrfs_release_path(path); + btrfs_release_path(&path); if (extent_disk_bytenr) real_disk_bytenr = cur_off - key.offset + @@ -357,7 +361,7 @@ static int record_file_blocks(struct blk_iterate_data *data, * need to waste CPU cycles now. */ } - btrfs_free_path(path); + btrfs_release_path(&path); return ret; } @@ -964,7 +968,7 @@ static int create_image(struct btrfs_root *root, { struct btrfs_inode_item buf; struct btrfs_trans_handle *trans; - struct btrfs_path *path = NULL; + struct btrfs_path path; struct btrfs_key key; struct cache_extent *cache; struct cache_tree used_tmp; @@ -981,6 +985,7 @@ static int create_image(struct btrfs_root *root, return -ENOMEM; cache_tree_init(&used_tmp); + btrfs_init_path(&path); ret = btrfs_find_free_objectid(trans, root, BTRFS_FIRST_FREE_OBJECTID, &ino); @@ -997,24 +1002,19 @@ static int create_image(struct btrfs_root *root, if (ret < 0) goto out; - path = btrfs_alloc_path(); - if (!path) { - ret = -ENOMEM; - goto out; - } key.objectid = ino; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - ret = btrfs_search_slot(trans, root, &key, path, 0, 1); + ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); if (ret) { ret = (ret > 0 ? -ENOENT : ret); goto out; } - read_extent_buffer(path->nodes[0], &buf, - btrfs_item_ptr_offset(path->nodes[0], path->slots[0]), + read_extent_buffer(path.nodes[0], &buf, + btrfs_item_ptr_offset(path.nodes[0], path.slots[0]), sizeof(buf)); - btrfs_release_path(path); + btrfs_release_path(&path); /* * Create a new used space cache, which doesn't contain the reserved @@ -1052,18 +1052,18 @@ static int create_image(struct btrfs_root *root, key.objectid = ino; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - ret = btrfs_search_slot(trans, root, &key, path, 0, 1); + ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); if (ret) { ret = (ret > 0 ? -ENOENT : ret); goto out; } btrfs_set_stack_inode_size(&buf, cfg->num_bytes); - write_extent_buffer(path->nodes[0], &buf, - btrfs_item_ptr_offset(path->nodes[0], path->slots[0]), + write_extent_buffer(path.nodes[0], &buf, + btrfs_item_ptr_offset(path.nodes[0], path.slots[0]), sizeof(buf)); out: free_extent_cache_tree(&used_tmp); - btrfs_free_path(path); + btrfs_release_path(&path); btrfs_commit_transaction(trans, root); return ret; } @@ -1075,7 +1075,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root, struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *new_root = NULL; - struct btrfs_path *path; + struct btrfs_path path; struct btrfs_inode_item *inode_item; struct extent_buffer *leaf; struct btrfs_key key; @@ -1090,28 +1090,25 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root, if (len == 0 || len > BTRFS_NAME_LEN) return NULL; - path = btrfs_alloc_path(); - if (!path) - return NULL; - + btrfs_init_path(&path); key.objectid = dirid; key.type = BTRFS_DIR_INDEX_KEY; key.offset = (u64)-1; - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret <= 0) { error("search for DIR_INDEX dirid %llu failed: %d", (unsigned long long)dirid, ret); goto fail; } - if (path->slots[0] > 0) { - path->slots[0]--; - btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); + if (path.slots[0] > 0) { + path.slots[0]--; + btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]); if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY) index = key.offset + 1; } - btrfs_release_path(path); + btrfs_release_path(&path); trans = btrfs_start_transaction(root, 1); if (!trans) { @@ -1123,14 +1120,14 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root, key.offset = 0; key.type = BTRFS_INODE_ITEM_KEY; - ret = btrfs_lookup_inode(trans, root, path, &key, 1); + ret = btrfs_lookup_inode(trans, root, &path, &key, 1); if (ret) { error("search for INODE_ITEM %llu failed: %d", (unsigned long long)dirid, ret); goto fail; } - leaf = path->nodes[0]; - inode_item = btrfs_item_ptr(leaf, path->slots[0], + leaf = path.nodes[0]; + inode_item = btrfs_item_ptr(leaf, path.slots[0], struct btrfs_inode_item); key.objectid = root_objectid; @@ -1155,7 +1152,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root, btrfs_set_inode_size(leaf, inode_item, len * 2 + btrfs_inode_size(leaf, inode_item)); btrfs_mark_buffer_dirty(leaf); - btrfs_release_path(path); + btrfs_release_path(&path); /* add the backref first */ ret = btrfs_add_root_ref(trans, tree_root, root_objectid, @@ -1190,7 +1187,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root, new_root = NULL; } fail: - btrfs_free_path(path); + btrfs_init_path(&path); return new_root; } @@ -1499,7 +1496,7 @@ static int ext2_open_fs(struct btrfs_convert_context *cctx, const char *name) if (!(ext2_fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)) { - fprintf(stderr, "filetype feature is missing\n"); + error("filetype feature is missing"); goto fail; } @@ -2183,6 +2180,42 @@ static void ext2_copy_inode_item(struct btrfs_inode_item *dst, } memset(&dst->reserved, 0, sizeof(dst->reserved)); } +static int ext2_check_state(struct btrfs_convert_context *cctx) +{ + ext2_filsys fs = cctx->fs_data; + + if (!(fs->super->s_state & EXT2_VALID_FS)) + return 1; + else if (fs->super->s_state & EXT2_ERROR_FS) + return 1; + else + return 0; +} + +/* EXT2_*_FL to BTRFS_INODE_FLAG_* stringification helper */ +#define COPY_ONE_EXT2_FLAG(flags, ext2_inode, name) ({ \ + if (ext2_inode->i_flags & EXT2_##name##_FL) \ + flags |= BTRFS_INODE_##name; \ +}) + +/* + * Convert EXT2_*_FL to corresponding BTRFS_INODE_* flags + * + * Only a subset of EXT_*_FL is supported in btrfs. + */ +static void ext2_convert_inode_flags(struct btrfs_inode_item *dst, + struct ext2_inode *src) +{ + u64 flags = 0; + + COPY_ONE_EXT2_FLAG(flags, src, APPEND); + COPY_ONE_EXT2_FLAG(flags, src, SYNC); + COPY_ONE_EXT2_FLAG(flags, src, IMMUTABLE); + COPY_ONE_EXT2_FLAG(flags, src, NODUMP); + COPY_ONE_EXT2_FLAG(flags, src, NOATIME); + COPY_ONE_EXT2_FLAG(flags, src, DIRSYNC); + btrfs_set_stack_inode_flags(dst, flags); +} /* * copy a single inode. do all the required works, such as cloning @@ -2206,6 +2239,7 @@ static int ext2_copy_single_inode(struct btrfs_trans_handle *trans, BTRFS_INODE_NODATASUM; btrfs_set_stack_inode_flags(&btrfs_inode, flags); } + ext2_convert_inode_flags(&btrfs_inode, ext2_inode); switch (ext2_inode->i_mode & S_IFMT) { case S_IFREG: @@ -2301,6 +2335,7 @@ static const struct btrfs_convert_operations ext2_convert_ops = { .read_used_space = ext2_read_used_space, .copy_inodes = ext2_copy_inodes, .close_fs = ext2_close_fs, + .check_state = ext2_check_state, }; #endif @@ -2327,7 +2362,7 @@ static int convert_open_fs(const char *devname, } } - fprintf(stderr, "No file system found to convert.\n"); + error("no file system found to convert"); return -1; } @@ -2352,6 +2387,10 @@ static int do_convert(const char *devname, int datacsum, int packing, ret = convert_open_fs(devname, &cctx); if (ret) goto fail; + ret = convert_check_state(&cctx); + if (ret) + warning( + "source filesystem is not clean, running filesystem check is recommended"); ret = convert_read_used_space(&cctx); if (ret) goto fail; @@ -2995,7 +3034,7 @@ static void print_usage(void) printf("\t-O|--features LIST comma separated list of filesystem features\n"); printf("\t--no-progress show only overview, not the detailed progress\n"); printf("\n"); - printf("Suported filesystems:\n"); + printf("Supported filesystems:\n"); printf("\text2/3/4: %s\n", BTRFSCONVERT_EXT2 ? "yes" : "no"); } @@ -3055,8 +3094,8 @@ int main(int argc, char *argv[]) case 'l': copylabel = -1; if (strlen(optarg) >= BTRFS_LABEL_SIZE) { - fprintf(stderr, - "WARNING: label too long, trimmed to %d bytes\n", + warning( + "label too long, trimmed to %d bytes", BTRFS_LABEL_SIZE - 1); } __strncpy_null(fslabel, optarg, BTRFS_LABEL_SIZE - 1); @@ -3073,8 +3112,7 @@ int main(int argc, char *argv[]) tmp = btrfs_parse_fs_features(tmp, &features); if (tmp) { - fprintf(stderr, - "Unrecognized filesystem feature '%s'\n", + error("unrecognized filesystem feature: %s", tmp); free(orig); exit(1); @@ -3090,8 +3128,7 @@ int main(int argc, char *argv[]) btrfs_parse_features_to_string(buf, features & ~BTRFS_CONVERT_ALLOWED_FEATURES); - fprintf(stderr, - "ERROR: features not allowed for convert: %s\n", + error("features not allowed for convert: %s", buf); exit(1); } @@ -3127,11 +3164,10 @@ int main(int argc, char *argv[]) file = argv[optind]; ret = check_mounted(file); if (ret < 0) { - fprintf(stderr, "Could not check mount status: %s\n", - strerror(-ret)); + error("could not check mount status: %s", strerror(-ret)); return 1; } else if (ret) { - fprintf(stderr, "%s is mounted\n", file); + error("%s is mounted", file); return 1; }