]> code.ossystems Code Review - openembedded-core.git/blob
f533c5b0b4f7bf328f3d265e7fc0edd399533216
[openembedded-core.git] /
1 Upstream-Status: Inappropriate [Backport]
2 From e7ef1f26a25d06d5606934dced7b52f3e33f1d33 Mon Sep 17 00:00:00 2001
3 From: Josef Bacik <josef@redhat.com>
4 Date: Thu, 9 Dec 2010 18:31:08 +0000
5 Subject: [PATCH 07/15] Btrfs-progs: add support for mixed data+metadata block groups
6
7 So alot of crazy people (I'm looking at you Meego) want to use btrfs on phones
8 and such with small devices.  Unfortunately the way we split out metadata/data
9 chunks it makes space usage inefficient for volumes that are smaller than
10 1gigabyte.  So add a -M option for mixing metadata+data, and default to this
11 mixed mode if the filesystem is less than or equal to 1 gigabyte.  I've tested
12 this with xfstests on a 100mb filesystem and everything is a-ok.
13
14 Signed-off-by: Josef Bacik <josef@redhat.com>
15 Signed-off-by: Chris Mason <chris.mason@oracle.com>
16 ---
17  btrfs-vol.c  |    4 +-
18  btrfs_cmds.c |   13 +++++-
19  ctree.h      |   10 +++--
20  mkfs.c       |  122 +++++++++++++++++++++++++++++++++++++++++-----------------
21  utils.c      |   10 ++--
22  utils.h      |    2 +-
23  6 files changed, 112 insertions(+), 49 deletions(-)
24
25 diff --git a/btrfs-vol.c b/btrfs-vol.c
26 index 4ed799d..f573023 100644
27 --- a/btrfs-vol.c
28 +++ b/btrfs-vol.c
29 @@ -143,7 +143,9 @@ int main(int ac, char **av)
30                 exit(1);
31         }
32         if (cmd == BTRFS_IOC_ADD_DEV) {
33 -               ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count);
34 +               int mixed = 0;
35 +
36 +               ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count, &mixed);
37                 if (ret) {
38                         fprintf(stderr, "Unable to init %s\n", device);
39                         exit(1);
40 diff --git a/btrfs_cmds.c b/btrfs_cmds.c
41 index 775bfe1..c21a007 100644
42 --- a/btrfs_cmds.c
43 +++ b/btrfs_cmds.c
44 @@ -720,6 +720,7 @@ int do_add_volume(int nargs, char **args)
45                 int     devfd, res;
46                 u64 dev_block_count = 0;
47                 struct stat st;
48 +               int mixed = 0;
49  
50                 devfd = open(args[i], O_RDWR);
51                 if (!devfd) {
52 @@ -742,7 +743,7 @@ int do_add_volume(int nargs, char **args)
53                         continue;
54                 }
55  
56 -               res = btrfs_prepare_device(devfd, args[i], 1, &dev_block_count);
57 +               res = btrfs_prepare_device(devfd, args[i], 1, &dev_block_count, &mixed);
58                 if (res) {
59                         fprintf(stderr, "ERROR: Unable to init '%s'\n", args[i]);
60                         close(devfd);
61 @@ -920,8 +921,14 @@ int do_df_filesystem(int nargs, char **argv)
62                 memset(description, 0, 80);
63  
64                 if (flags & BTRFS_BLOCK_GROUP_DATA) {
65 -                       snprintf(description, 5, "%s", "Data");
66 -                       written += 4;
67 +                       if (flags & BTRFS_BLOCK_GROUP_METADATA) {
68 +                               snprintf(description, 15, "%s",
69 +                                        "Data+Metadata");
70 +                               written += 14;
71 +                       } else {
72 +                               snprintf(description, 5, "%s", "Data");
73 +                               written += 4;
74 +                       }
75                 } else if (flags & BTRFS_BLOCK_GROUP_SYSTEM) {
76                         snprintf(description, 7, "%s", "System");
77                         written += 6;
78 diff --git a/ctree.h b/ctree.h
79 index 962c510..ed83d02 100644
80 --- a/ctree.h
81 +++ b/ctree.h
82 @@ -352,13 +352,15 @@ struct btrfs_super_block {
83   * ones specified below then we will fail to mount
84   */
85  #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF   (1ULL << 0)
86 -#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL  (2ULL << 0)
87 +#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL  (1ULL << 1)
88 +#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS    (1ULL << 2)
89  
90  #define BTRFS_FEATURE_COMPAT_SUPP              0ULL
91  #define BTRFS_FEATURE_COMPAT_RO_SUPP           0ULL
92 -#define BTRFS_FEATURE_INCOMPAT_SUPP            \
93 -       (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
94 -        BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL)
95 +#define BTRFS_FEATURE_INCOMPAT_SUPP                    \
96 +       (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |         \
97 +        BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |        \
98 +        BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS)
99  
100  /*
101   * A leaf is full of items. offset and size tell us where to find
102 diff --git a/mkfs.c b/mkfs.c
103 index 2e99b95..04de93a 100644
104 --- a/mkfs.c
105 +++ b/mkfs.c
106 @@ -69,7 +69,7 @@ static u64 parse_size(char *s)
107         return atol(s) * mult;
108  }
109  
110 -static int make_root_dir(struct btrfs_root *root)
111 +static int make_root_dir(struct btrfs_root *root, int mixed)
112  {
113         struct btrfs_trans_handle *trans;
114         struct btrfs_key location;
115 @@ -88,30 +88,47 @@ static int make_root_dir(struct btrfs_root *root)
116                                      0, BTRFS_MKFS_SYSTEM_GROUP_SIZE);
117         BUG_ON(ret);
118  
119 -       ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
120 -                               &chunk_start, &chunk_size,
121 -                               BTRFS_BLOCK_GROUP_METADATA);
122 -       BUG_ON(ret);
123 -       ret = btrfs_make_block_group(trans, root, 0,
124 -                                    BTRFS_BLOCK_GROUP_METADATA,
125 -                                    BTRFS_FIRST_CHUNK_TREE_OBJECTID,
126 -                                    chunk_start, chunk_size);
127 -       BUG_ON(ret);
128 +       if (mixed) {
129 +               ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
130 +                                       &chunk_start, &chunk_size,
131 +                                       BTRFS_BLOCK_GROUP_METADATA |
132 +                                       BTRFS_BLOCK_GROUP_DATA);
133 +               BUG_ON(ret);
134 +               ret = btrfs_make_block_group(trans, root, 0,
135 +                                            BTRFS_BLOCK_GROUP_METADATA |
136 +                                            BTRFS_BLOCK_GROUP_DATA,
137 +                                            BTRFS_FIRST_CHUNK_TREE_OBJECTID,
138 +                                            chunk_start, chunk_size);
139 +               BUG_ON(ret);
140 +               printf("Created a data/metadata chunk of size %llu\n", chunk_size);
141 +       } else {
142 +               ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
143 +                                       &chunk_start, &chunk_size,
144 +                                       BTRFS_BLOCK_GROUP_METADATA);
145 +               BUG_ON(ret);
146 +               ret = btrfs_make_block_group(trans, root, 0,
147 +                                            BTRFS_BLOCK_GROUP_METADATA,
148 +                                            BTRFS_FIRST_CHUNK_TREE_OBJECTID,
149 +                                            chunk_start, chunk_size);
150 +               BUG_ON(ret);
151 +       }
152  
153         root->fs_info->system_allocs = 0;
154         btrfs_commit_transaction(trans, root);
155         trans = btrfs_start_transaction(root, 1);
156         BUG_ON(!trans);
157  
158 -       ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
159 -                               &chunk_start, &chunk_size,
160 -                               BTRFS_BLOCK_GROUP_DATA);
161 -       BUG_ON(ret);
162 -       ret = btrfs_make_block_group(trans, root, 0,
163 -                                    BTRFS_BLOCK_GROUP_DATA,
164 -                                    BTRFS_FIRST_CHUNK_TREE_OBJECTID,
165 -                                    chunk_start, chunk_size);
166 -       BUG_ON(ret);
167 +       if (!mixed) {
168 +               ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
169 +                                       &chunk_start, &chunk_size,
170 +                                       BTRFS_BLOCK_GROUP_DATA);
171 +               BUG_ON(ret);
172 +               ret = btrfs_make_block_group(trans, root, 0,
173 +                                            BTRFS_BLOCK_GROUP_DATA,
174 +                                            BTRFS_FIRST_CHUNK_TREE_OBJECTID,
175 +                                            chunk_start, chunk_size);
176 +               BUG_ON(ret);
177 +       }
178  
179         ret = btrfs_make_root_dir(trans, root->fs_info->tree_root,
180                               BTRFS_ROOT_TREE_DIR_OBJECTID);
181 @@ -200,7 +217,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
182  
183  static int create_raid_groups(struct btrfs_trans_handle *trans,
184                               struct btrfs_root *root, u64 data_profile,
185 -                             u64 metadata_profile)
186 +                             u64 metadata_profile, int mixed)
187  {
188         u64 num_devices = btrfs_super_num_devices(&root->fs_info->super_copy);
189         u64 allowed;
190 @@ -215,20 +232,24 @@ static int create_raid_groups(struct btrfs_trans_handle *trans,
191                 allowed = BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1;
192  
193         if (allowed & metadata_profile) {
194 +               u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA;
195 +
196                 ret = create_one_raid_group(trans, root,
197                                             BTRFS_BLOCK_GROUP_SYSTEM |
198                                             (allowed & metadata_profile));
199                 BUG_ON(ret);
200  
201 -               ret = create_one_raid_group(trans, root,
202 -                                           BTRFS_BLOCK_GROUP_METADATA |
203 +               if (mixed)
204 +                       meta_flags |= BTRFS_BLOCK_GROUP_DATA;
205 +
206 +               ret = create_one_raid_group(trans, root, meta_flags |
207                                             (allowed & metadata_profile));
208                 BUG_ON(ret);
209  
210                 ret = recow_roots(trans, root);
211                 BUG_ON(ret);
212         }
213 -       if (num_devices > 1 && (allowed & data_profile)) {
214 +       if (!mixed && num_devices > 1 && (allowed & data_profile)) {
215                 ret = create_one_raid_group(trans, root,
216                                             BTRFS_BLOCK_GROUP_DATA |
217                                             (allowed & data_profile));
218 @@ -274,6 +295,7 @@ static void print_usage(void)
219         fprintf(stderr, "\t -l --leafsize size of btree leaves\n");
220         fprintf(stderr, "\t -L --label set a label\n");
221         fprintf(stderr, "\t -m --metadata metadata profile, values like data profile\n");
222 +       fprintf(stderr, "\t -M --mixed mix metadata and data together\n");
223         fprintf(stderr, "\t -n --nodesize size of btree nodes\n");
224         fprintf(stderr, "\t -s --sectorsize min block allocation\n");
225         fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION);
226 @@ -328,6 +350,7 @@ static struct option long_options[] = {
227         { "leafsize", 1, NULL, 'l' },
228         { "label", 1, NULL, 'L'},
229         { "metadata", 1, NULL, 'm' },
230 +       { "mixed", 0, NULL, 'M' },
231         { "nodesize", 1, NULL, 'n' },
232         { "sectorsize", 1, NULL, 's' },
233         { "data", 1, NULL, 'd' },
234 @@ -358,10 +381,13 @@ int main(int ac, char **av)
235         int first_fd;
236         int ret;
237         int i;
238 +       int mixed = 0;
239 +       int data_profile_opt = 0;
240 +       int metadata_profile_opt = 0;
241  
242         while(1) {
243                 int c;
244 -               c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:V", long_options,
245 +               c = getopt_long(ac, av, "A:b:l:n:s:m:d:L:VM", long_options,
246                                 &option_index);
247                 if (c < 0)
248                         break;
249 @@ -371,6 +397,7 @@ int main(int ac, char **av)
250                                 break;
251                         case 'd':
252                                 data_profile = parse_profile(optarg);
253 +                               data_profile_opt = 1;
254                                 break;
255                         case 'l':
256                                 leafsize = parse_size(optarg);
257 @@ -380,6 +407,10 @@ int main(int ac, char **av)
258                                 break;
259                         case 'm':
260                                 metadata_profile = parse_profile(optarg);
261 +                               metadata_profile_opt = 1;
262 +                               break;
263 +                       case 'M':
264 +                               mixed = 1;
265                                 break;
266                         case 'n':
267                                 nodesize = parse_size(optarg);
268 @@ -389,12 +420,10 @@ int main(int ac, char **av)
269                                 break;
270                         case 'b':
271                                 block_count = parse_size(optarg);
272 -                               if (block_count < 256*1024*1024) {
273 -                                       fprintf(stderr, "File system size "
274 -                                               "%llu bytes is too small, "
275 -                                               "256M is required at least\n",
276 -                                               (unsigned long long)block_count);
277 -                                       exit(1);
278 +                               if (block_count <= 1024*1024*1024) {
279 +                                       printf("SMALL VOLUME: forcing mixed "
280 +                                              "metadata/data groups\n");
281 +                                       mixed = 1;
282                                 }
283                                 zero_end = 0;
284                                 break;
285 @@ -439,9 +468,22 @@ int main(int ac, char **av)
286         }
287         first_fd = fd;
288         first_file = file;
289 -       ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count);
290 +       ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count,
291 +                                  &mixed);
292         if (block_count == 0)
293                 block_count = dev_block_count;
294 +       if (mixed) {
295 +               if (!metadata_profile_opt)
296 +                       metadata_profile = 0;
297 +               if (!data_profile_opt)
298 +                       data_profile = 0;
299 +
300 +               if (metadata_profile != data_profile) {
301 +                       fprintf(stderr, "With mixed block groups data and metadata "
302 +                               "profiles must be the same\n");
303 +                       exit(1);
304 +               }
305 +       }
306  
307         blocks[0] = BTRFS_SUPER_INFO_OFFSET;
308         for (i = 1; i < 7; i++) {
309 @@ -459,7 +501,7 @@ int main(int ac, char **av)
310         root = open_ctree(file, 0, O_RDWR);
311         root->fs_info->alloc_start = alloc_start;
312  
313 -       ret = make_root_dir(root);
314 +       ret = make_root_dir(root, mixed);
315         if (ret) {
316                 fprintf(stderr, "failed to setup the root directory\n");
317                 exit(1);
318 @@ -478,6 +520,8 @@ int main(int ac, char **av)
319  
320         zero_end = 1;
321         while(ac-- > 0) {
322 +               int old_mixed = mixed;
323 +
324                 file = av[optind++];
325                 ret = check_mounted(file);
326                 if (ret < 0) {
327 @@ -503,8 +547,8 @@ int main(int ac, char **av)
328                         continue;
329                 }
330                 ret = btrfs_prepare_device(fd, file, zero_end,
331 -                                          &dev_block_count);
332 -
333 +                                          &dev_block_count, &mixed);
334 +               mixed = old_mixed;
335                 BUG_ON(ret);
336  
337                 ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count,
338 @@ -515,12 +559,20 @@ int main(int ac, char **av)
339  
340  raid_groups:
341         ret = create_raid_groups(trans, root, data_profile,
342 -                                metadata_profile);
343 +                                metadata_profile, mixed);
344         BUG_ON(ret);
345  
346         ret = create_data_reloc_tree(trans, root);
347         BUG_ON(ret);
348  
349 +       if (mixed) {
350 +               struct btrfs_super_block *super = &root->fs_info->super_copy;
351 +               u64 flags = btrfs_super_incompat_flags(super);
352 +
353 +               flags |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS;
354 +               btrfs_set_super_incompat_flags(super, flags);
355 +       }
356 +
357         printf("fs created label %s on %s\n\tnodesize %u leafsize %u "
358             "sectorsize %u size %s\n",
359             label, first_file, nodesize, leafsize, sectorsize,
360 diff --git a/utils.c b/utils.c
361 index 35e17b8..ad980ae 100644
362 --- a/utils.c
363 +++ b/utils.c
364 @@ -512,7 +512,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
365         return 0;
366  }
367  
368 -int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret)
369 +int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
370 +                        int *mixed)
371  {
372         u64 block_count;
373         u64 bytenr;
374 @@ -532,10 +533,9 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret)
375         }
376         zero_end = 1;
377  
378 -       if (block_count < 256 * 1024 * 1024) {
379 -               fprintf(stderr, "device %s is too small "
380 -                       "(must be at least 256 MB)\n", file);
381 -               exit(1);
382 +       if (block_count < 1024 * 1024 * 1024 && !(*mixed)) {
383 +               printf("SMALL VOLUME: forcing mixed metadata/data groups\n");
384 +               *mixed = 1;
385         }
386         ret = zero_dev_start(fd);
387         if (ret) {
388 diff --git a/utils.h b/utils.h
389 index 9dce5b0..a28d7f4 100644
390 --- a/utils.h
391 +++ b/utils.h
392 @@ -27,7 +27,7 @@ int make_btrfs(int fd, const char *device, const char *label,
393  int btrfs_make_root_dir(struct btrfs_trans_handle *trans,
394                         struct btrfs_root *root, u64 objectid);
395  int btrfs_prepare_device(int fd, char *file, int zero_end,
396 -                        u64 *block_count_ret);
397 +                        u64 *block_count_ret, int *mixed);
398  int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
399                       struct btrfs_root *root, int fd, char *path,
400                       u64 block_count, u32 io_width, u32 io_align,
401 -- 
402 1.7.2.3
403