diff options
Diffstat (limited to 'meta/recipes-devtools/btrfs-tools/btrfs-tools/upstream-tmp/0007-Btrfs-progs-add-support-for-mixed-data-metadata-bloc.patch')
-rw-r--r-- | meta/recipes-devtools/btrfs-tools/btrfs-tools/upstream-tmp/0007-Btrfs-progs-add-support-for-mixed-data-metadata-bloc.patch | 403 |
1 files changed, 403 insertions, 0 deletions
diff --git a/meta/recipes-devtools/btrfs-tools/btrfs-tools/upstream-tmp/0007-Btrfs-progs-add-support-for-mixed-data-metadata-bloc.patch b/meta/recipes-devtools/btrfs-tools/btrfs-tools/upstream-tmp/0007-Btrfs-progs-add-support-for-mixed-data-metadata-bloc.patch new file mode 100644 index 0000000000..f533c5b0b4 --- /dev/null +++ b/meta/recipes-devtools/btrfs-tools/btrfs-tools/upstream-tmp/0007-Btrfs-progs-add-support-for-mixed-data-metadata-bloc.patch @@ -0,0 +1,403 @@ +Upstream-Status: Inappropriate [Backport] +From e7ef1f26a25d06d5606934dced7b52f3e33f1d33 Mon Sep 17 00:00:00 2001 +From: Josef Bacik <josef@redhat.com> +Date: Thu, 9 Dec 2010 18:31:08 +0000 +Subject: [PATCH 07/15] Btrfs-progs: add support for mixed data+metadata block groups + +So alot of crazy people (I'm looking at you Meego) want to use btrfs on phones +and such with small devices. Unfortunately the way we split out metadata/data +chunks it makes space usage inefficient for volumes that are smaller than +1gigabyte. So add a -M option for mixing metadata+data, and default to this +mixed mode if the filesystem is less than or equal to 1 gigabyte. I've tested +this with xfstests on a 100mb filesystem and everything is a-ok. + +Signed-off-by: Josef Bacik <josef@redhat.com> +Signed-off-by: Chris Mason <chris.mason@oracle.com> +--- + btrfs-vol.c | 4 +- + btrfs_cmds.c | 13 +++++- + ctree.h | 10 +++-- + mkfs.c | 122 +++++++++++++++++++++++++++++++++++++++++----------------- + utils.c | 10 ++-- + utils.h | 2 +- + 6 files changed, 112 insertions(+), 49 deletions(-) + +diff --git a/btrfs-vol.c b/btrfs-vol.c +index 4ed799d..f573023 100644 +--- a/btrfs-vol.c ++++ b/btrfs-vol.c +@@ -143,7 +143,9 @@ int main(int ac, char **av) + exit(1); + } + if (cmd == BTRFS_IOC_ADD_DEV) { +- ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count); ++ int mixed = 0; ++ ++ ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count, &mixed); + if (ret) { + fprintf(stderr, "Unable to init %s\n", device); + exit(1); +diff --git a/btrfs_cmds.c b/btrfs_cmds.c +index 775bfe1..c21a007 100644 +--- a/btrfs_cmds.c ++++ b/btrfs_cmds.c +@@ -720,6 +720,7 @@ int do_add_volume(int nargs, char **args) + int devfd, res; + u64 dev_block_count = 0; + struct stat st; ++ int mixed = 0; + + devfd = open(args[i], O_RDWR); + if (!devfd) { +@@ -742,7 +743,7 @@ int do_add_volume(int nargs, char **args) + continue; + } + +- res = btrfs_prepare_device(devfd, args[i], 1, &dev_block_count); ++ res = btrfs_prepare_device(devfd, args[i], 1, &dev_block_count, &mixed); + if (res) { + fprintf(stderr, "ERROR: Unable to init '%s'\n", args[i]); + close(devfd); +@@ -920,8 +921,14 @@ int do_df_filesystem(int nargs, char **argv) + memset(description, 0, 80); + + if (flags & BTRFS_BLOCK_GROUP_DATA) { +- snprintf(description, 5, "%s", "Data"); +- written += 4; ++ if (flags & BTRFS_BLOCK_GROUP_METADATA) { ++ snprintf(description, 15, "%s", ++ "Data+Metadata"); ++ written += 14; ++ } else { ++ snprintf(description, 5, "%s", "Data"); ++ written += 4; ++ } + } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) { + snprintf(description, 7, "%s", "System"); + written += 6; +diff --git a/ctree.h b/ctree.h +index 962c510..ed83d02 100644 +--- a/ctree.h ++++ b/ctree.h +@@ -352,13 +352,15 @@ struct btrfs_super_block { + * ones specified below then we will fail to mount + */ + #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) +-#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0) ++#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) ++#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) + + #define BTRFS_FEATURE_COMPAT_SUPP 0ULL + #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL +-#define BTRFS_FEATURE_INCOMPAT_SUPP \ +- (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ +- BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL) ++#define BTRFS_FEATURE_INCOMPAT_SUPP \ ++ (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ ++ BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \ ++ BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) + + /* + * A leaf is full of items. offset and size tell us where to find +diff --git a/mkfs.c b/mkfs.c +index 2e99b95..04de93a 100644 +--- a/mkfs.c ++++ b/mkfs.c +@@ -69,7 +69,7 @@ static u64 parse_size(char *s) + return atol(s) * mult; + } + +-static int make_root_dir(struct btrfs_root *root) ++static int make_root_dir(struct btrfs_root *root, int mixed) + { + struct btrfs_trans_handle *trans; + struct btrfs_key location; +@@ -88,30 +88,47 @@ static int make_root_dir(struct btrfs_root *root) + 0, BTRFS_MKFS_SYSTEM_GROUP_SIZE); + BUG_ON(ret); + +- ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, +- &chunk_start, &chunk_size, +- BTRFS_BLOCK_GROUP_METADATA); +- BUG_ON(ret); +- ret = btrfs_make_block_group(trans, root, 0, +- BTRFS_BLOCK_GROUP_METADATA, +- BTRFS_FIRST_CHUNK_TREE_OBJECTID, +- chunk_start, chunk_size); +- BUG_ON(ret); ++ if (mixed) { ++ ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, ++ &chunk_start, &chunk_size, ++ BTRFS_BLOCK_GROUP_METADATA | ++ BTRFS_BLOCK_GROUP_DATA); ++ BUG_ON(ret); ++ ret = btrfs_make_block_group(trans, root, 0, ++ BTRFS_BLOCK_GROUP_METADATA | ++ BTRFS_BLOCK_GROUP_DATA, ++ BTRFS_FIRST_CHUNK_TREE_OBJECTID, ++ chunk_start, chunk_size); ++ BUG_ON(ret); ++ printf("Created a data/metadata chunk of size %llu\n", chunk_size); ++ } else { ++ ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, ++ &chunk_start, &chunk_size, ++ BTRFS_BLOCK_GROUP_METADATA); ++ BUG_ON(ret); ++ ret = btrfs_make_block_group(trans, root, 0, ++ BTRFS_BLOCK_GROUP_METADATA, ++ BTRFS_FIRST_CHUNK_TREE_OBJECTID, ++ chunk_start, chunk_size); ++ BUG_ON(ret); ++ } + + root->fs_info->system_allocs = 0; + btrfs_commit_transaction(trans, root); + trans = btrfs_start_transaction(root, 1); + BUG_ON(!trans); + +- ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, +- &chunk_start, &chunk_size, +- BTRFS_BLOCK_GROUP_DATA); +- BUG_ON(ret); +- ret = btrfs_make_block_group(trans, root, 0, +- BTRFS_BLOCK_GROUP_DATA, +- BTRFS_FIRST_CHUNK_TREE_OBJECTID, +- chunk_start, chunk_size); +- BUG_ON(ret); ++ if (!mixed) { ++ ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root, ++ &chunk_start, &chunk_size, ++ BTRFS_BLOCK_GROUP_DATA); ++ BUG_ON(ret); ++ ret = btrfs_make_block_group(trans, root, 0, ++ BTRFS_BLOCK_GROUP_DATA, ++ BTRFS_FIRST_CHUNK_TREE_OBJECTID, ++ chunk_start, chunk_size); ++ BUG_ON(ret); ++ } + + ret = btrfs_make_root_dir(trans, root->fs_info->tree_root, + BTRFS_ROOT_TREE_DIR_OBJECTID); +@@ -200,7 +217,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans, + + static int create_raid_groups(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 data_profile, +- u64 metadata_profile) ++ u64 metadata_profile, int mixed) + { + u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy); + u64 allowed; +@@ -215,20 +232,24 @@ static int create_raid_groups(struct btrfs_trans_handle *trans, + allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1; + + if (allowed & metadata_profile) { ++ u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA; ++ + ret = create_one_raid_group(trans, root, + BTRFS_BLOCK_GROUP_SYSTEM | + (allowed & metadata_profile)); + BUG_ON(ret); + +- ret = create_one_raid_group(trans, root, +- BTRFS_BLOCK_GROUP_METADATA | ++ if (mixed) ++ meta_flags |= BTRFS_BLOCK_GROUP_DATA; ++ ++ ret = create_one_raid_group(trans, root, meta_flags | + (allowed & metadata_profile)); + BUG_ON(ret); + + ret = recow_roots(trans, root); + BUG_ON(ret); + } +- if (num_devices > 1 && (allowed & data_profile)) { ++ if (!mixed && num_devices > 1 && (allowed & data_profile)) { + ret = create_one_raid_group(trans, root, + BTRFS_BLOCK_GROUP_DATA | + (allowed & data_profile)); +@@ -274,6 +295,7 @@ static void print_usage(void) + fprintf(stderr, "\t -l --leafsize size of btree leaves\n"); + fprintf(stderr, "\t -L --label set a label\n"); + fprintf(stderr, "\t -m --metadata metadata profile, values like data profile\n"); ++ fprintf(stderr, "\t -M --mixed mix metadata and data together\n"); + fprintf(stderr, "\t -n --nodesize size of btree nodes\n"); + fprintf(stderr, "\t -s --sectorsize min block allocation\n"); + fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION); +@@ -328,6 +350,7 @@ static struct option long_options[] = { + { "leafsize", 1, NULL, 'l' }, + { "label", 1, NULL, 'L'}, + { "metadata", 1, NULL, 'm' }, ++ { "mixed", 0, NULL, 'M' }, + { "nodesize", 1, NULL, 'n' }, + { "sectorsize", 1, NULL, 's' }, + { "data", 1, NULL, 'd' }, +@@ -358,10 +381,13 @@ int main(int ac, char **av) + int first_fd; + int ret; + int i; ++ int mixed = 0; ++ int data_profile_opt = 0; ++ int metadata_profile_opt = 0; + + while(1) { + int c; +- c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:V", long_options, ++ c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:VM", long_options, + &option_index); + if (c < 0) + break; +@@ -371,6 +397,7 @@ int main(int ac, char **av) + break; + case 'd': + data_profile = parse_profile(optarg); ++ data_profile_opt = 1; + break; + case 'l': + leafsize = parse_size(optarg); +@@ -380,6 +407,10 @@ int main(int ac, char **av) + break; + case 'm': + metadata_profile = parse_profile(optarg); ++ metadata_profile_opt = 1; ++ break; ++ case 'M': ++ mixed = 1; + break; + case 'n': + nodesize = parse_size(optarg); +@@ -389,12 +420,10 @@ int main(int ac, char **av) + break; + case 'b': + block_count = parse_size(optarg); +- if (block_count < 256*1024*1024) { +- fprintf(stderr, "File system size " +- "%llu bytes is too small, " +- "256M is required at least\n", +- (unsigned long long)block_count); +- exit(1); ++ if (block_count <= 1024*1024*1024) { ++ printf("SMALL VOLUME: forcing mixed " ++ "metadata/data groups\n"); ++ mixed = 1; + } + zero_end = 0; + break; +@@ -439,9 +468,22 @@ int main(int ac, char **av) + } + first_fd = fd; + first_file = file; +- ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count); ++ ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, ++ &mixed); + if (block_count == 0) + block_count = dev_block_count; ++ if (mixed) { ++ if (!metadata_profile_opt) ++ metadata_profile = 0; ++ if (!data_profile_opt) ++ data_profile = 0; ++ ++ if (metadata_profile != data_profile) { ++ fprintf(stderr, "With mixed block groups data and metadata " ++ "profiles must be the same\n"); ++ exit(1); ++ } ++ } + + blocks[0] = BTRFS_SUPER_INFO_OFFSET; + for (i = 1; i < 7; i++) { +@@ -459,7 +501,7 @@ int main(int ac, char **av) + root = open_ctree(file, 0, O_RDWR); + root->fs_info->alloc_start = alloc_start; + +- ret = make_root_dir(root); ++ ret = make_root_dir(root, mixed); + if (ret) { + fprintf(stderr, "failed to setup the root directory\n"); + exit(1); +@@ -478,6 +520,8 @@ int main(int ac, char **av) + + zero_end = 1; + while(ac-- > 0) { ++ int old_mixed = mixed; ++ + file = av[optind++]; + ret = check_mounted(file); + if (ret < 0) { +@@ -503,8 +547,8 @@ int main(int ac, char **av) + continue; + } + ret = btrfs_prepare_device(fd, file, zero_end, +- &dev_block_count); +- ++ &dev_block_count, &mixed); ++ mixed = old_mixed; + BUG_ON(ret); + + ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count, +@@ -515,12 +559,20 @@ int main(int ac, char **av) + + raid_groups: + ret = create_raid_groups(trans, root, data_profile, +- metadata_profile); ++ metadata_profile, mixed); + BUG_ON(ret); + + ret = create_data_reloc_tree(trans, root); + BUG_ON(ret); + ++ if (mixed) { ++ struct btrfs_super_block *super = &root->fs_info->super_copy; ++ u64 flags = btrfs_super_incompat_flags(super); ++ ++ flags |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS; ++ btrfs_set_super_incompat_flags(super, flags); ++ } ++ + printf("fs created label %s on %s\n\tnodesize %u leafsize %u " + "sectorsize %u size %s\n", + label, first_file, nodesize, leafsize, sectorsize, +diff --git a/utils.c b/utils.c +index 35e17b8..ad980ae 100644 +--- a/utils.c ++++ b/utils.c +@@ -512,7 +512,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, + return 0; + } + +-int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret) ++int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret, ++ int *mixed) + { + u64 block_count; + u64 bytenr; +@@ -532,10 +533,9 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret) + } + zero_end = 1; + +- if (block_count < 256 * 1024 * 1024) { +- fprintf(stderr, "device %s is too small " +- "(must be at least 256 MB)\n", file); +- exit(1); ++ if (block_count < 1024 * 1024 * 1024 && !(*mixed)) { ++ printf("SMALL VOLUME: forcing mixed metadata/data groups\n"); ++ *mixed = 1; + } + ret = zero_dev_start(fd); + if (ret) { +diff --git a/utils.h b/utils.h +index 9dce5b0..a28d7f4 100644 +--- a/utils.h ++++ b/utils.h +@@ -27,7 +27,7 @@ int make_btrfs(int fd, const char *device, const char *label, + int btrfs_make_root_dir(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 objectid); + int btrfs_prepare_device(int fd, char *file, int zero_end, +- u64 *block_count_ret); ++ u64 *block_count_ret, int *mixed); + int btrfs_add_to_fsid(struct btrfs_trans_handle *trans, + struct btrfs_root *root, int fd, char *path, + u64 block_count, u32 io_width, u32 io_align, +-- +1.7.2.3 + |