* [PATCH] Btrfs-progs: add support for mixed data+metadata block groups
@ 2010-12-09 18:31 Josef Bacik
2011-04-08 7:31 ` liubo
0 siblings, 1 reply; 4+ messages in thread
From: Josef Bacik @ 2010-12-09 18:31 UTC (permalink / raw)
To: linux-btrfs
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>
---
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 8069778..7200bbc 100644
--- a/btrfs-vol.c
+++ b/btrfs-vol.c
@@ -129,7 +129,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 8031c58..683aec0 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -705,6 +705,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) {
@@ -727,7 +728,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);
@@ -889,8 +890,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 b890728..13d31b7 100644
--- a/utils.c
+++ b/utils.c
@@ -508,7 +508,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;
@@ -528,10 +529,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 7ff542b..b91140e 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.6.6.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] Btrfs-progs: add support for mixed data+metadata block groups
2010-12-09 18:31 [PATCH] Btrfs-progs: add support for mixed data+metadata block groups Josef Bacik
@ 2011-04-08 7:31 ` liubo
2011-04-08 13:15 ` Josef Bacik
0 siblings, 1 reply; 4+ messages in thread
From: liubo @ 2011-04-08 7:31 UTC (permalink / raw)
To: Josef Bacik; +Cc: linux-btrfs
On 12/10/2010 02:31 AM, Josef Bacik wrote:
> 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.
>
Hi, Josef,
While using this mix metadata+data option, I noticed the following from btrfs-debug-tree's print:
===
chunk tree
leaf 143360 items 4 free space 3557 generation 4 owner 3
fs uuid 77d78a87-a886-4bfa-be3b-0dd052213a17
chunk uuid e64148d6-8267-4ff1-aafd-4266f74afbb2
item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 3897 itemsize 98
dev item devid 1 total_bytes 4999610368 bytes used 20971520
item 1 key (FIRST_CHUNK_TREE CHUNK_ITEM 0) itemoff 3817 itemsize 80
chunk length 4194304 owner 2 type 2 num_stripes 1
stripe 0 devid 1 offset 0
item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 4194304) itemoff 3737 itemsize 80
chunk length 8388608 owner 2 type 5 num_stripes 1
stripe 0 devid 1 offset 4194304
item 3 key (FIRST_CHUNK_TREE CHUNK_ITEM 12582912) itemoff 3657 itemsize 80 <== THIS ONE
chunk length 8388608 owner 2 type 4 num_stripes 1 <==
stripe 0 devid 1 offset 12582912 <==
===
you see, there exists another metadata chunk (type 4) after "mkfs.btrfs -M /dev/xxx".
So I was wondering that _IS_ this chunk what we want, or a spare one?
thanks,
liubo
> Signed-off-by: Josef Bacik <josef@redhat.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 8069778..7200bbc 100644
> --- a/btrfs-vol.c
> +++ b/btrfs-vol.c
> @@ -129,7 +129,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 8031c58..683aec0 100644
> --- a/btrfs_cmds.c
> +++ b/btrfs_cmds.c
> @@ -705,6 +705,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) {
> @@ -727,7 +728,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);
> @@ -889,8 +890,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 b890728..13d31b7 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -508,7 +508,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;
> @@ -528,10 +529,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 7ff542b..b91140e 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,
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] Btrfs-progs: add support for mixed data+metadata block groups
2011-04-08 7:31 ` liubo
@ 2011-04-08 13:15 ` Josef Bacik
0 siblings, 0 replies; 4+ messages in thread
From: Josef Bacik @ 2011-04-08 13:15 UTC (permalink / raw)
To: liubo; +Cc: linux-btrfs
On 04/08/2011 03:31 AM, liubo wrote:
> On 12/10/2010 02:31 AM, Josef Bacik wrote:
>> 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.
>>
>
> Hi, Josef,
>
> While using this mix metadata+data option, I noticed the following from btrfs-debug-tree's print:
>
> ===
> chunk tree
> leaf 143360 items 4 free space 3557 generation 4 owner 3
> fs uuid 77d78a87-a886-4bfa-be3b-0dd052213a17
> chunk uuid e64148d6-8267-4ff1-aafd-4266f74afbb2
> item 0 key (DEV_ITEMS DEV_ITEM 1) itemoff 3897 itemsize 98
> dev item devid 1 total_bytes 4999610368 bytes used 20971520
> item 1 key (FIRST_CHUNK_TREE CHUNK_ITEM 0) itemoff 3817 itemsize 80
> chunk length 4194304 owner 2 type 2 num_stripes 1
> stripe 0 devid 1 offset 0
> item 2 key (FIRST_CHUNK_TREE CHUNK_ITEM 4194304) itemoff 3737 itemsize 80
> chunk length 8388608 owner 2 type 5 num_stripes 1
> stripe 0 devid 1 offset 4194304
> item 3 key (FIRST_CHUNK_TREE CHUNK_ITEM 12582912) itemoff 3657 itemsize 80<== THIS ONE
> chunk length 8388608 owner 2 type 4 num_stripes 1 <==
> stripe 0 devid 1 offset 12582912 <==
> ===
>
> you see, there exists another metadata chunk (type 4) after "mkfs.btrfs -M /dev/xxx".
> So I was wondering that _IS_ this chunk what we want, or a spare one?
>
Hmm that shouldn't be there, thanks for catching that, we should only be
creating a system block_group and a mixed block_group, not another
metadata one. I will fix that up.
Josef
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] Btrfs-progs: add support for mixed data+metadata block groups
@ 2010-09-16 20:16 Josef Bacik
0 siblings, 0 replies; 4+ messages in thread
From: Josef Bacik @ 2010-09-16 20:16 UTC (permalink / raw)
To: linux-btrfs
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>
---
btrfs-vol.c | 4 +-
btrfs_cmds.c | 13 +++++-
mkfs.c | 121 ++++++++++++++++++++++++++++++++++++++++------------------
utils.c | 10 ++--
utils.h | 2 +-
5 files changed, 103 insertions(+), 47 deletions(-)
diff --git a/btrfs-vol.c b/btrfs-vol.c
index 8069778..7200bbc 100644
--- a/btrfs-vol.c
+++ b/btrfs-vol.c
@@ -129,7 +129,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 8031c58..683aec0 100644
--- a/btrfs_cmds.c
+++ b/btrfs_cmds.c
@@ -705,6 +705,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) {
@@ -727,7 +728,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);
@@ -889,8 +890,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/mkfs.c b/mkfs.c
index 2e99b95..4610f58 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' },
@@ -346,8 +369,8 @@ int main(int ac, char **av)
u64 dev_block_count = 0;
u64 blocks[7];
u64 alloc_start = 0;
- u64 metadata_profile = BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP;
- u64 data_profile = BTRFS_BLOCK_GROUP_RAID0;
+ u64 metadata_profile = 0;
+ u64 data_profile = 0;
u32 leafsize = getpagesize();
u32 sectorsize = 4096;
u32 nodesize = leafsize;
@@ -358,10 +381,11 @@ int main(int ac, char **av)
int first_fd;
int ret;
int i;
+ int mixed = 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;
@@ -381,6 +405,9 @@ int main(int ac, char **av)
case 'm':
metadata_profile = parse_profile(optarg);
break;
+ case 'M':
+ mixed = 1;
+ break;
case 'n':
nodesize = parse_size(optarg);
break;
@@ -389,12 +416,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,10 +464,30 @@ 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 != data_profile) {
+ fprintf(stderr, "To use mixed metadata/data you must "
+ "have the same allocation profiles\n");
+ exit(1);
+ }
+ } else if (!metadata_profile || !data_profile) {
+ /*
+ * If we didn't set a data or metadata profile, just use some
+ * defaults, later on we'll figure out if these are appropriate
+ * or not.
+ */
+ if (!metadata_profile)
+ metadata_profile = BTRFS_BLOCK_GROUP_RAID1 |
+ BTRFS_BLOCK_GROUP_DUP;
+ if (!data_profile)
+ data_profile = BTRFS_BLOCK_GROUP_RAID0;
+ }
+
blocks[0] = BTRFS_SUPER_INFO_OFFSET;
for (i = 1; i < 7; i++) {
blocks[i] = BTRFS_SUPER_INFO_OFFSET + 1024 * 1024 +
@@ -459,7 +504,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 +523,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 +550,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,7 +562,7 @@ 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);
diff --git a/utils.c b/utils.c
index 2f4c6e1..0de43df 100644
--- a/utils.c
+++ b/utils.c
@@ -507,7 +507,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;
@@ -527,10 +528,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 7ff542b..b91140e 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.6.6.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2011-04-08 13:15 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-12-09 18:31 [PATCH] Btrfs-progs: add support for mixed data+metadata block groups Josef Bacik
2011-04-08 7:31 ` liubo
2011-04-08 13:15 ` Josef Bacik
-- strict thread matches above, loose matches on Subject: below --
2010-09-16 20:16 Josef Bacik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).