114572d558
- remove debugging printf from 0001-Btrfs-progs-add-a-btrfs-select-super-command-to-over.patch (forwarded request 76766 from dsterba) OBS-URL: https://build.opensuse.org/request/show/76976 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/btrfsprogs?expand=0&rev=22
404 lines
13 KiB
Diff
404 lines
13 KiB
Diff
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.5.2.353.g5df3e
|
|
|