btrfs-progs: add new flag to read superblock with mismatched fsids
[btrfs-progs-unstable/devel.git] / convert / common.c
blob6ddf4a46ce3c49dc8f531ae089317b9509911651
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public
4 * License v2 as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * General Public License for more details.
11 * You should have received a copy of the GNU General Public
12 * License along with this program; if not, write to the
13 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14 * Boston, MA 021110-1307, USA.
17 #include <unistd.h>
18 #include <uuid/uuid.h>
19 #include "disk-io.h"
20 #include "volumes.h"
21 #include "utils.h"
22 #include "mkfs/common.h"
23 #include "convert/common.h"
25 #define BTRFS_CONVERT_META_GROUP_SIZE SZ_32M
28 * Reserve space from free_tree.
29 * The algorithm is very simple, find the first cache_extent with enough space
30 * and allocate from its beginning.
32 static int reserve_free_space(struct cache_tree *free_tree, u64 len,
33 u64 *ret_start)
35 struct cache_extent *cache;
36 int found = 0;
38 ASSERT(ret_start != NULL);
39 cache = first_cache_extent(free_tree);
40 while (cache) {
41 if (cache->size > len) {
42 found = 1;
43 *ret_start = cache->start;
45 cache->size -= len;
46 if (cache->size == 0) {
47 remove_cache_extent(free_tree, cache);
48 free(cache);
49 } else {
50 cache->start += len;
52 break;
54 cache = next_cache_extent(cache);
56 if (!found)
57 return -ENOSPC;
58 return 0;
61 static inline int write_temp_super(int fd, struct btrfs_super_block *sb,
62 u64 sb_bytenr)
64 u32 crc = ~(u32)0;
65 int ret;
67 crc = btrfs_csum_data((char *)sb + BTRFS_CSUM_SIZE, crc,
68 BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
69 btrfs_csum_final(crc, &sb->csum[0]);
70 ret = pwrite(fd, sb, BTRFS_SUPER_INFO_SIZE, sb_bytenr);
71 if (ret < BTRFS_SUPER_INFO_SIZE)
72 ret = (ret < 0 ? -errno : -EIO);
73 else
74 ret = 0;
75 return ret;
79 * Setup temporary superblock at cfg->super_bynter
80 * Needed info are extracted from cfg, and root_bytenr, chunk_bytenr
82 * For now sys chunk array will be empty and dev_item is empty too.
83 * They will be re-initialized at temp chunk tree setup.
85 * The superblock signature is not valid, denotes a partially created
86 * filesystem, needs to be finalized.
88 static int setup_temp_super(int fd, struct btrfs_mkfs_config *cfg,
89 u64 root_bytenr, u64 chunk_bytenr)
91 unsigned char chunk_uuid[BTRFS_UUID_SIZE];
92 char super_buf[BTRFS_SUPER_INFO_SIZE];
93 struct btrfs_super_block *super = (struct btrfs_super_block *)super_buf;
94 int ret;
96 memset(super_buf, 0, BTRFS_SUPER_INFO_SIZE);
97 cfg->num_bytes = round_down(cfg->num_bytes, cfg->sectorsize);
99 if (*cfg->fs_uuid) {
100 if (uuid_parse(cfg->fs_uuid, super->fsid) != 0) {
101 error("cound not parse UUID: %s", cfg->fs_uuid);
102 ret = -EINVAL;
103 goto out;
105 if (!test_uuid_unique(cfg->fs_uuid)) {
106 error("non-unique UUID: %s", cfg->fs_uuid);
107 ret = -EINVAL;
108 goto out;
110 } else {
111 uuid_generate(super->fsid);
112 uuid_unparse(super->fsid, cfg->fs_uuid);
114 uuid_generate(chunk_uuid);
115 uuid_unparse(chunk_uuid, cfg->chunk_uuid);
117 btrfs_set_super_bytenr(super, cfg->super_bytenr);
118 btrfs_set_super_num_devices(super, 1);
119 btrfs_set_super_magic(super, BTRFS_MAGIC_TEMPORARY);
120 btrfs_set_super_generation(super, 1);
121 btrfs_set_super_root(super, root_bytenr);
122 btrfs_set_super_chunk_root(super, chunk_bytenr);
123 btrfs_set_super_total_bytes(super, cfg->num_bytes);
125 * Temporary filesystem will only have 6 tree roots:
126 * chunk tree, root tree, extent_tree, device tree, fs tree
127 * and csum tree.
129 btrfs_set_super_bytes_used(super, 6 * cfg->nodesize);
130 btrfs_set_super_sectorsize(super, cfg->sectorsize);
131 super->__unused_leafsize = cpu_to_le32(cfg->nodesize);
132 btrfs_set_super_nodesize(super, cfg->nodesize);
133 btrfs_set_super_stripesize(super, cfg->stripesize);
134 btrfs_set_super_csum_type(super, BTRFS_CSUM_TYPE_CRC32);
135 btrfs_set_super_chunk_root(super, chunk_bytenr);
136 btrfs_set_super_cache_generation(super, -1);
137 btrfs_set_super_incompat_flags(super, cfg->features);
138 if (cfg->label)
139 __strncpy_null(super->label, cfg->label, BTRFS_LABEL_SIZE - 1);
141 /* Sys chunk array will be re-initialized at chunk tree init time */
142 super->sys_chunk_array_size = 0;
144 ret = write_temp_super(fd, super, cfg->super_bytenr);
145 out:
146 return ret;
149 static int setup_temp_extent_buffer(struct extent_buffer *buf,
150 struct btrfs_mkfs_config *cfg,
151 u64 bytenr, u64 owner)
153 unsigned char fsid[BTRFS_FSID_SIZE];
154 unsigned char chunk_uuid[BTRFS_UUID_SIZE];
155 int ret;
157 ret = uuid_parse(cfg->fs_uuid, fsid);
158 if (ret)
159 return -EINVAL;
160 ret = uuid_parse(cfg->chunk_uuid, chunk_uuid);
161 if (ret)
162 return -EINVAL;
164 memset(buf->data, 0, cfg->nodesize);
165 buf->len = cfg->nodesize;
166 btrfs_set_header_bytenr(buf, bytenr);
167 btrfs_set_header_generation(buf, 1);
168 btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV);
169 btrfs_set_header_owner(buf, owner);
170 btrfs_set_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN);
171 write_extent_buffer(buf, chunk_uuid, btrfs_header_chunk_tree_uuid(buf),
172 BTRFS_UUID_SIZE);
173 write_extent_buffer(buf, fsid, btrfs_header_fsid(), BTRFS_FSID_SIZE);
174 return 0;
177 static void insert_temp_root_item(struct extent_buffer *buf,
178 struct btrfs_mkfs_config *cfg,
179 int *slot, u32 *itemoff, u64 objectid,
180 u64 bytenr)
182 struct btrfs_root_item root_item;
183 struct btrfs_inode_item *inode_item;
184 struct btrfs_disk_key disk_key;
186 btrfs_set_header_nritems(buf, *slot + 1);
187 (*itemoff) -= sizeof(root_item);
188 memset(&root_item, 0, sizeof(root_item));
189 inode_item = &root_item.inode;
190 btrfs_set_stack_inode_generation(inode_item, 1);
191 btrfs_set_stack_inode_size(inode_item, 3);
192 btrfs_set_stack_inode_nlink(inode_item, 1);
193 btrfs_set_stack_inode_nbytes(inode_item, cfg->nodesize);
194 btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
195 btrfs_set_root_refs(&root_item, 1);
196 btrfs_set_root_used(&root_item, cfg->nodesize);
197 btrfs_set_root_generation(&root_item, 1);
198 btrfs_set_root_bytenr(&root_item, bytenr);
200 memset(&disk_key, 0, sizeof(disk_key));
201 btrfs_set_disk_key_type(&disk_key, BTRFS_ROOT_ITEM_KEY);
202 btrfs_set_disk_key_objectid(&disk_key, objectid);
203 btrfs_set_disk_key_offset(&disk_key, 0);
205 btrfs_set_item_key(buf, &disk_key, *slot);
206 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
207 btrfs_set_item_size(buf, btrfs_item_nr(*slot), sizeof(root_item));
208 write_extent_buffer(buf, &root_item,
209 btrfs_item_ptr_offset(buf, *slot),
210 sizeof(root_item));
211 (*slot)++;
215 * Setup an extent buffer for tree block.
217 static inline int write_temp_extent_buffer(int fd, struct extent_buffer *buf,
218 u64 bytenr)
220 int ret;
222 csum_tree_block_size(buf, btrfs_csum_sizes[BTRFS_CSUM_TYPE_CRC32], 0);
224 /* Temporary extent buffer is always mapped 1:1 on disk */
225 ret = pwrite(fd, buf->data, buf->len, bytenr);
226 if (ret < buf->len)
227 ret = (ret < 0 ? ret : -EIO);
228 else
229 ret = 0;
230 return ret;
233 static int setup_temp_root_tree(int fd, struct btrfs_mkfs_config *cfg,
234 u64 root_bytenr, u64 extent_bytenr,
235 u64 dev_bytenr, u64 fs_bytenr, u64 csum_bytenr)
237 struct extent_buffer *buf = NULL;
238 u32 itemoff = __BTRFS_LEAF_DATA_SIZE(cfg->nodesize);
239 int slot = 0;
240 int ret;
243 * Provided bytenr must in ascending order, or tree root will have a
244 * bad key order.
246 if (!(root_bytenr < extent_bytenr && extent_bytenr < dev_bytenr &&
247 dev_bytenr < fs_bytenr && fs_bytenr < csum_bytenr)) {
248 error("bad tree bytenr order: "
249 "root < extent %llu < %llu, "
250 "extent < dev %llu < %llu, "
251 "dev < fs %llu < %llu, "
252 "fs < csum %llu < %llu",
253 (unsigned long long)root_bytenr,
254 (unsigned long long)extent_bytenr,
255 (unsigned long long)extent_bytenr,
256 (unsigned long long)dev_bytenr,
257 (unsigned long long)dev_bytenr,
258 (unsigned long long)fs_bytenr,
259 (unsigned long long)fs_bytenr,
260 (unsigned long long)csum_bytenr);
261 return -EINVAL;
263 buf = malloc(sizeof(*buf) + cfg->nodesize);
264 if (!buf)
265 return -ENOMEM;
267 ret = setup_temp_extent_buffer(buf, cfg, root_bytenr,
268 BTRFS_ROOT_TREE_OBJECTID);
269 if (ret < 0)
270 goto out;
272 insert_temp_root_item(buf, cfg, &slot, &itemoff,
273 BTRFS_EXTENT_TREE_OBJECTID, extent_bytenr);
274 insert_temp_root_item(buf, cfg, &slot, &itemoff,
275 BTRFS_DEV_TREE_OBJECTID, dev_bytenr);
276 insert_temp_root_item(buf, cfg, &slot, &itemoff,
277 BTRFS_FS_TREE_OBJECTID, fs_bytenr);
278 insert_temp_root_item(buf, cfg, &slot, &itemoff,
279 BTRFS_CSUM_TREE_OBJECTID, csum_bytenr);
281 ret = write_temp_extent_buffer(fd, buf, root_bytenr);
282 out:
283 free(buf);
284 return ret;
287 static int insert_temp_dev_item(int fd, struct extent_buffer *buf,
288 struct btrfs_mkfs_config *cfg,
289 int *slot, u32 *itemoff)
291 struct btrfs_disk_key disk_key;
292 struct btrfs_dev_item *dev_item;
293 char super_buf[BTRFS_SUPER_INFO_SIZE];
294 unsigned char dev_uuid[BTRFS_UUID_SIZE];
295 unsigned char fsid[BTRFS_FSID_SIZE];
296 struct btrfs_super_block *super = (struct btrfs_super_block *)super_buf;
297 int ret;
299 ret = pread(fd, super_buf, BTRFS_SUPER_INFO_SIZE, cfg->super_bytenr);
300 if (ret < BTRFS_SUPER_INFO_SIZE) {
301 ret = (ret < 0 ? -errno : -EIO);
302 goto out;
305 btrfs_set_header_nritems(buf, *slot + 1);
306 (*itemoff) -= sizeof(*dev_item);
307 /* setup device item 1, 0 is for replace case */
308 btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_ITEM_KEY);
309 btrfs_set_disk_key_objectid(&disk_key, BTRFS_DEV_ITEMS_OBJECTID);
310 btrfs_set_disk_key_offset(&disk_key, 1);
311 btrfs_set_item_key(buf, &disk_key, *slot);
312 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
313 btrfs_set_item_size(buf, btrfs_item_nr(*slot), sizeof(*dev_item));
315 dev_item = btrfs_item_ptr(buf, *slot, struct btrfs_dev_item);
316 /* Generate device uuid */
317 uuid_generate(dev_uuid);
318 write_extent_buffer(buf, dev_uuid,
319 (unsigned long)btrfs_device_uuid(dev_item),
320 BTRFS_UUID_SIZE);
321 uuid_parse(cfg->fs_uuid, fsid);
322 write_extent_buffer(buf, fsid,
323 (unsigned long)btrfs_device_fsid(dev_item),
324 BTRFS_FSID_SIZE);
325 btrfs_set_device_id(buf, dev_item, 1);
326 btrfs_set_device_generation(buf, dev_item, 0);
327 btrfs_set_device_total_bytes(buf, dev_item, cfg->num_bytes);
329 * The number must match the initial SYSTEM and META chunk size
331 btrfs_set_device_bytes_used(buf, dev_item,
332 BTRFS_MKFS_SYSTEM_GROUP_SIZE +
333 BTRFS_CONVERT_META_GROUP_SIZE);
334 btrfs_set_device_io_align(buf, dev_item, cfg->sectorsize);
335 btrfs_set_device_io_width(buf, dev_item, cfg->sectorsize);
336 btrfs_set_device_sector_size(buf, dev_item, cfg->sectorsize);
337 btrfs_set_device_type(buf, dev_item, 0);
339 /* Super dev_item is not complete, copy the complete one to sb */
340 read_extent_buffer(buf, &super->dev_item, (unsigned long)dev_item,
341 sizeof(*dev_item));
342 ret = write_temp_super(fd, super, cfg->super_bytenr);
343 (*slot)++;
344 out:
345 return ret;
348 static int insert_temp_chunk_item(int fd, struct extent_buffer *buf,
349 struct btrfs_mkfs_config *cfg,
350 int *slot, u32 *itemoff, u64 start, u64 len,
351 u64 type)
353 struct btrfs_chunk *chunk;
354 struct btrfs_disk_key disk_key;
355 char super_buf[BTRFS_SUPER_INFO_SIZE];
356 struct btrfs_super_block *sb = (struct btrfs_super_block *)super_buf;
357 int ret = 0;
359 ret = pread(fd, super_buf, BTRFS_SUPER_INFO_SIZE,
360 cfg->super_bytenr);
361 if (ret < BTRFS_SUPER_INFO_SIZE) {
362 ret = (ret < 0 ? ret : -EIO);
363 return ret;
366 btrfs_set_header_nritems(buf, *slot + 1);
367 (*itemoff) -= btrfs_chunk_item_size(1);
368 btrfs_set_disk_key_type(&disk_key, BTRFS_CHUNK_ITEM_KEY);
369 btrfs_set_disk_key_objectid(&disk_key, BTRFS_FIRST_CHUNK_TREE_OBJECTID);
370 btrfs_set_disk_key_offset(&disk_key, start);
371 btrfs_set_item_key(buf, &disk_key, *slot);
372 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
373 btrfs_set_item_size(buf, btrfs_item_nr(*slot),
374 btrfs_chunk_item_size(1));
376 chunk = btrfs_item_ptr(buf, *slot, struct btrfs_chunk);
377 btrfs_set_chunk_length(buf, chunk, len);
378 btrfs_set_chunk_owner(buf, chunk, BTRFS_EXTENT_TREE_OBJECTID);
379 btrfs_set_chunk_stripe_len(buf, chunk, BTRFS_STRIPE_LEN);
380 btrfs_set_chunk_type(buf, chunk, type);
381 btrfs_set_chunk_io_align(buf, chunk, cfg->sectorsize);
382 btrfs_set_chunk_io_width(buf, chunk, cfg->sectorsize);
383 btrfs_set_chunk_sector_size(buf, chunk, cfg->sectorsize);
384 btrfs_set_chunk_num_stripes(buf, chunk, 1);
385 /* TODO: Support DUP profile for system chunk */
386 btrfs_set_stripe_devid_nr(buf, chunk, 0, 1);
387 /* We are doing 1:1 mapping, so start is its dev offset */
388 btrfs_set_stripe_offset_nr(buf, chunk, 0, start);
389 write_extent_buffer(buf, &sb->dev_item.uuid,
390 (unsigned long)btrfs_stripe_dev_uuid_nr(chunk, 0),
391 BTRFS_UUID_SIZE);
392 (*slot)++;
395 * If it's system chunk, also copy it to super block.
397 if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
398 char *cur;
399 u32 array_size;
401 cur = (char *)sb->sys_chunk_array
402 + btrfs_super_sys_array_size(sb);
403 memcpy(cur, &disk_key, sizeof(disk_key));
404 cur += sizeof(disk_key);
405 read_extent_buffer(buf, cur, (unsigned long int)chunk,
406 btrfs_chunk_item_size(1));
407 array_size = btrfs_super_sys_array_size(sb);
408 array_size += btrfs_chunk_item_size(1) +
409 sizeof(disk_key);
410 btrfs_set_super_sys_array_size(sb, array_size);
412 ret = write_temp_super(fd, sb, cfg->super_bytenr);
414 return ret;
417 static int setup_temp_chunk_tree(int fd, struct btrfs_mkfs_config *cfg,
418 u64 sys_chunk_start, u64 meta_chunk_start,
419 u64 chunk_bytenr)
421 struct extent_buffer *buf = NULL;
422 u32 itemoff = __BTRFS_LEAF_DATA_SIZE(cfg->nodesize);
423 int slot = 0;
424 int ret;
426 /* Must ensure SYS chunk starts before META chunk */
427 if (meta_chunk_start < sys_chunk_start) {
428 error("wrong chunk order: meta < system %llu < %llu",
429 (unsigned long long)meta_chunk_start,
430 (unsigned long long)sys_chunk_start);
431 return -EINVAL;
433 buf = malloc(sizeof(*buf) + cfg->nodesize);
434 if (!buf)
435 return -ENOMEM;
436 ret = setup_temp_extent_buffer(buf, cfg, chunk_bytenr,
437 BTRFS_CHUNK_TREE_OBJECTID);
438 if (ret < 0)
439 goto out;
441 ret = insert_temp_dev_item(fd, buf, cfg, &slot, &itemoff);
442 if (ret < 0)
443 goto out;
444 ret = insert_temp_chunk_item(fd, buf, cfg, &slot, &itemoff,
445 sys_chunk_start,
446 BTRFS_MKFS_SYSTEM_GROUP_SIZE,
447 BTRFS_BLOCK_GROUP_SYSTEM);
448 if (ret < 0)
449 goto out;
450 ret = insert_temp_chunk_item(fd, buf, cfg, &slot, &itemoff,
451 meta_chunk_start,
452 BTRFS_CONVERT_META_GROUP_SIZE,
453 BTRFS_BLOCK_GROUP_METADATA);
454 if (ret < 0)
455 goto out;
456 ret = write_temp_extent_buffer(fd, buf, chunk_bytenr);
458 out:
459 free(buf);
460 return ret;
463 static void insert_temp_dev_extent(struct extent_buffer *buf,
464 int *slot, u32 *itemoff, u64 start, u64 len)
466 struct btrfs_dev_extent *dev_extent;
467 struct btrfs_disk_key disk_key;
469 btrfs_set_header_nritems(buf, *slot + 1);
470 (*itemoff) -= sizeof(*dev_extent);
471 btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_EXTENT_KEY);
472 btrfs_set_disk_key_objectid(&disk_key, 1);
473 btrfs_set_disk_key_offset(&disk_key, start);
474 btrfs_set_item_key(buf, &disk_key, *slot);
475 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
476 btrfs_set_item_size(buf, btrfs_item_nr(*slot), sizeof(*dev_extent));
478 dev_extent = btrfs_item_ptr(buf, *slot, struct btrfs_dev_extent);
479 btrfs_set_dev_extent_chunk_objectid(buf, dev_extent,
480 BTRFS_FIRST_CHUNK_TREE_OBJECTID);
481 btrfs_set_dev_extent_length(buf, dev_extent, len);
482 btrfs_set_dev_extent_chunk_offset(buf, dev_extent, start);
483 btrfs_set_dev_extent_chunk_tree(buf, dev_extent,
484 BTRFS_CHUNK_TREE_OBJECTID);
485 (*slot)++;
488 static int setup_temp_dev_tree(int fd, struct btrfs_mkfs_config *cfg,
489 u64 sys_chunk_start, u64 meta_chunk_start,
490 u64 dev_bytenr)
492 struct extent_buffer *buf = NULL;
493 u32 itemoff = __BTRFS_LEAF_DATA_SIZE(cfg->nodesize);
494 int slot = 0;
495 int ret;
497 /* Must ensure SYS chunk starts before META chunk */
498 if (meta_chunk_start < sys_chunk_start) {
499 error("wrong chunk order: meta < system %llu < %llu",
500 (unsigned long long)meta_chunk_start,
501 (unsigned long long)sys_chunk_start);
502 return -EINVAL;
504 buf = malloc(sizeof(*buf) + cfg->nodesize);
505 if (!buf)
506 return -ENOMEM;
507 ret = setup_temp_extent_buffer(buf, cfg, dev_bytenr,
508 BTRFS_DEV_TREE_OBJECTID);
509 if (ret < 0)
510 goto out;
511 insert_temp_dev_extent(buf, &slot, &itemoff, sys_chunk_start,
512 BTRFS_MKFS_SYSTEM_GROUP_SIZE);
513 insert_temp_dev_extent(buf, &slot, &itemoff, meta_chunk_start,
514 BTRFS_CONVERT_META_GROUP_SIZE);
515 ret = write_temp_extent_buffer(fd, buf, dev_bytenr);
516 out:
517 free(buf);
518 return ret;
521 static int setup_temp_fs_tree(int fd, struct btrfs_mkfs_config *cfg,
522 u64 fs_bytenr)
524 struct extent_buffer *buf = NULL;
525 int ret;
527 buf = malloc(sizeof(*buf) + cfg->nodesize);
528 if (!buf)
529 return -ENOMEM;
530 ret = setup_temp_extent_buffer(buf, cfg, fs_bytenr,
531 BTRFS_FS_TREE_OBJECTID);
532 if (ret < 0)
533 goto out;
535 * Temporary fs tree is completely empty.
537 ret = write_temp_extent_buffer(fd, buf, fs_bytenr);
538 out:
539 free(buf);
540 return ret;
543 static int setup_temp_csum_tree(int fd, struct btrfs_mkfs_config *cfg,
544 u64 csum_bytenr)
546 struct extent_buffer *buf = NULL;
547 int ret;
549 buf = malloc(sizeof(*buf) + cfg->nodesize);
550 if (!buf)
551 return -ENOMEM;
552 ret = setup_temp_extent_buffer(buf, cfg, csum_bytenr,
553 BTRFS_CSUM_TREE_OBJECTID);
554 if (ret < 0)
555 goto out;
557 * Temporary csum tree is completely empty.
559 ret = write_temp_extent_buffer(fd, buf, csum_bytenr);
560 out:
561 free(buf);
562 return ret;
566 * Insert one temporary extent item.
568 * NOTE: if skinny_metadata is not enabled, this function must be called
569 * after all other trees are initialized.
570 * Or fs without skinny-metadata will be screwed up.
572 static int insert_temp_extent_item(int fd, struct extent_buffer *buf,
573 struct btrfs_mkfs_config *cfg,
574 int *slot, u32 *itemoff, u64 bytenr,
575 u64 ref_root)
577 struct extent_buffer *tmp;
578 struct btrfs_extent_item *ei;
579 struct btrfs_extent_inline_ref *iref;
580 struct btrfs_disk_key disk_key;
581 struct btrfs_disk_key tree_info_key;
582 struct btrfs_tree_block_info *info;
583 int itemsize;
584 int skinny_metadata = cfg->features &
585 BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA;
586 int ret;
588 if (skinny_metadata)
589 itemsize = sizeof(*ei) + sizeof(*iref);
590 else
591 itemsize = sizeof(*ei) + sizeof(*iref) +
592 sizeof(struct btrfs_tree_block_info);
594 btrfs_set_header_nritems(buf, *slot + 1);
595 *(itemoff) -= itemsize;
597 if (skinny_metadata) {
598 btrfs_set_disk_key_type(&disk_key, BTRFS_METADATA_ITEM_KEY);
599 btrfs_set_disk_key_offset(&disk_key, 0);
600 } else {
601 btrfs_set_disk_key_type(&disk_key, BTRFS_EXTENT_ITEM_KEY);
602 btrfs_set_disk_key_offset(&disk_key, cfg->nodesize);
604 btrfs_set_disk_key_objectid(&disk_key, bytenr);
606 btrfs_set_item_key(buf, &disk_key, *slot);
607 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
608 btrfs_set_item_size(buf, btrfs_item_nr(*slot), itemsize);
610 ei = btrfs_item_ptr(buf, *slot, struct btrfs_extent_item);
611 btrfs_set_extent_refs(buf, ei, 1);
612 btrfs_set_extent_generation(buf, ei, 1);
613 btrfs_set_extent_flags(buf, ei, BTRFS_EXTENT_FLAG_TREE_BLOCK);
615 if (skinny_metadata) {
616 iref = (struct btrfs_extent_inline_ref *)(ei + 1);
617 } else {
618 info = (struct btrfs_tree_block_info *)(ei + 1);
619 iref = (struct btrfs_extent_inline_ref *)(info + 1);
621 btrfs_set_extent_inline_ref_type(buf, iref,
622 BTRFS_TREE_BLOCK_REF_KEY);
623 btrfs_set_extent_inline_ref_offset(buf, iref, ref_root);
625 (*slot)++;
626 if (skinny_metadata)
627 return 0;
630 * Lastly, check the tree block key by read the tree block
631 * Since we do 1:1 mapping for convert case, we can directly
632 * read the bytenr from disk
634 tmp = malloc(sizeof(*tmp) + cfg->nodesize);
635 if (!tmp)
636 return -ENOMEM;
637 ret = setup_temp_extent_buffer(tmp, cfg, bytenr, ref_root);
638 if (ret < 0)
639 goto out;
640 ret = pread(fd, tmp->data, cfg->nodesize, bytenr);
641 if (ret < cfg->nodesize) {
642 ret = (ret < 0 ? -errno : -EIO);
643 goto out;
645 if (btrfs_header_nritems(tmp) == 0) {
646 btrfs_set_disk_key_type(&tree_info_key, 0);
647 btrfs_set_disk_key_objectid(&tree_info_key, 0);
648 btrfs_set_disk_key_offset(&tree_info_key, 0);
649 } else {
650 btrfs_item_key(tmp, &tree_info_key, 0);
652 btrfs_set_tree_block_key(buf, info, &tree_info_key);
654 out:
655 free(tmp);
656 return ret;
659 static void insert_temp_block_group(struct extent_buffer *buf,
660 struct btrfs_mkfs_config *cfg,
661 int *slot, u32 *itemoff,
662 u64 bytenr, u64 len, u64 used, u64 flag)
664 struct btrfs_block_group_item bgi;
665 struct btrfs_disk_key disk_key;
667 btrfs_set_header_nritems(buf, *slot + 1);
668 (*itemoff) -= sizeof(bgi);
669 btrfs_set_disk_key_type(&disk_key, BTRFS_BLOCK_GROUP_ITEM_KEY);
670 btrfs_set_disk_key_objectid(&disk_key, bytenr);
671 btrfs_set_disk_key_offset(&disk_key, len);
672 btrfs_set_item_key(buf, &disk_key, *slot);
673 btrfs_set_item_offset(buf, btrfs_item_nr(*slot), *itemoff);
674 btrfs_set_item_size(buf, btrfs_item_nr(*slot), sizeof(bgi));
676 btrfs_set_block_group_flags(&bgi, flag);
677 btrfs_set_block_group_used(&bgi, used);
678 btrfs_set_block_group_chunk_objectid(&bgi,
679 BTRFS_FIRST_CHUNK_TREE_OBJECTID);
680 write_extent_buffer(buf, &bgi, btrfs_item_ptr_offset(buf, *slot),
681 sizeof(bgi));
682 (*slot)++;
685 static int setup_temp_extent_tree(int fd, struct btrfs_mkfs_config *cfg,
686 u64 chunk_bytenr, u64 root_bytenr,
687 u64 extent_bytenr, u64 dev_bytenr,
688 u64 fs_bytenr, u64 csum_bytenr)
690 struct extent_buffer *buf = NULL;
691 u32 itemoff = __BTRFS_LEAF_DATA_SIZE(cfg->nodesize);
692 int slot = 0;
693 int ret;
696 * We must ensure provided bytenr are in ascending order,
697 * or extent tree key order will be broken.
699 if (!(chunk_bytenr < root_bytenr && root_bytenr < extent_bytenr &&
700 extent_bytenr < dev_bytenr && dev_bytenr < fs_bytenr &&
701 fs_bytenr < csum_bytenr)) {
702 error("bad tree bytenr order: "
703 "chunk < root %llu < %llu, "
704 "root < extent %llu < %llu, "
705 "extent < dev %llu < %llu, "
706 "dev < fs %llu < %llu, "
707 "fs < csum %llu < %llu",
708 (unsigned long long)chunk_bytenr,
709 (unsigned long long)root_bytenr,
710 (unsigned long long)root_bytenr,
711 (unsigned long long)extent_bytenr,
712 (unsigned long long)extent_bytenr,
713 (unsigned long long)dev_bytenr,
714 (unsigned long long)dev_bytenr,
715 (unsigned long long)fs_bytenr,
716 (unsigned long long)fs_bytenr,
717 (unsigned long long)csum_bytenr);
718 return -EINVAL;
720 buf = malloc(sizeof(*buf) + cfg->nodesize);
721 if (!buf)
722 return -ENOMEM;
724 ret = setup_temp_extent_buffer(buf, cfg, extent_bytenr,
725 BTRFS_EXTENT_TREE_OBJECTID);
726 if (ret < 0)
727 goto out;
729 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
730 chunk_bytenr, BTRFS_CHUNK_TREE_OBJECTID);
731 if (ret < 0)
732 goto out;
734 insert_temp_block_group(buf, cfg, &slot, &itemoff, chunk_bytenr,
735 BTRFS_MKFS_SYSTEM_GROUP_SIZE, cfg->nodesize,
736 BTRFS_BLOCK_GROUP_SYSTEM);
738 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
739 root_bytenr, BTRFS_ROOT_TREE_OBJECTID);
740 if (ret < 0)
741 goto out;
743 /* 5 tree block used, root, extent, dev, fs and csum*/
744 insert_temp_block_group(buf, cfg, &slot, &itemoff, root_bytenr,
745 BTRFS_CONVERT_META_GROUP_SIZE, cfg->nodesize * 5,
746 BTRFS_BLOCK_GROUP_METADATA);
748 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
749 extent_bytenr, BTRFS_EXTENT_TREE_OBJECTID);
750 if (ret < 0)
751 goto out;
752 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
753 dev_bytenr, BTRFS_DEV_TREE_OBJECTID);
754 if (ret < 0)
755 goto out;
756 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
757 fs_bytenr, BTRFS_FS_TREE_OBJECTID);
758 if (ret < 0)
759 goto out;
760 ret = insert_temp_extent_item(fd, buf, cfg, &slot, &itemoff,
761 csum_bytenr, BTRFS_CSUM_TREE_OBJECTID);
762 if (ret < 0)
763 goto out;
765 ret = write_temp_extent_buffer(fd, buf, extent_bytenr);
766 out:
767 free(buf);
768 return ret;
772 * Improved version of make_btrfs().
774 * This one will
775 * 1) Do chunk allocation to avoid used data
776 * And after this function, extent type matches chunk type
777 * 2) Better structured code
778 * No super long hand written codes to initialized all tree blocks
779 * Split into small blocks and reuse codes.
780 * TODO: Reuse tree operation facilities by introducing new flags
782 int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
783 struct btrfs_convert_context *cctx)
785 struct cache_tree *free_space = &cctx->free_space;
786 struct cache_tree *used_space = &cctx->used_space;
787 u64 sys_chunk_start;
788 u64 meta_chunk_start;
789 /* chunk tree bytenr, in system chunk */
790 u64 chunk_bytenr;
791 /* metadata trees bytenr, in metadata chunk */
792 u64 root_bytenr;
793 u64 extent_bytenr;
794 u64 dev_bytenr;
795 u64 fs_bytenr;
796 u64 csum_bytenr;
797 int ret;
799 /* Source filesystem must be opened, checked and analyzed in advance */
800 ASSERT(!cache_tree_empty(used_space));
803 * reserve space for temporary superblock first
804 * Here we allocate a little larger space, to keep later
805 * free space will be STRIPE_LEN aligned
807 ret = reserve_free_space(free_space, BTRFS_STRIPE_LEN,
808 &cfg->super_bytenr);
809 if (ret < 0)
810 goto out;
813 * Then reserve system chunk space
814 * TODO: Change system group size depending on cctx->total_bytes.
815 * If using current 4M, it can only handle less than one TB for
816 * worst case and then run out of sys space.
818 ret = reserve_free_space(free_space, BTRFS_MKFS_SYSTEM_GROUP_SIZE,
819 &sys_chunk_start);
820 if (ret < 0)
821 goto out;
822 ret = reserve_free_space(free_space, BTRFS_CONVERT_META_GROUP_SIZE,
823 &meta_chunk_start);
824 if (ret < 0)
825 goto out;
828 * Allocated meta/sys chunks will be mapped 1:1 with device offset.
830 * Inside the allocated metadata chunk, the layout will be:
831 * | offset | contents |
832 * -------------------------------------
833 * | +0 | tree root |
834 * | +nodesize | extent root |
835 * | +nodesize * 2 | device root |
836 * | +nodesize * 3 | fs tree |
837 * | +nodesize * 4 | csum tree |
838 * -------------------------------------
839 * Inside the allocated system chunk, the layout will be:
840 * | offset | contents |
841 * -------------------------------------
842 * | +0 | chunk root |
843 * -------------------------------------
845 chunk_bytenr = sys_chunk_start;
846 root_bytenr = meta_chunk_start;
847 extent_bytenr = meta_chunk_start + cfg->nodesize;
848 dev_bytenr = meta_chunk_start + cfg->nodesize * 2;
849 fs_bytenr = meta_chunk_start + cfg->nodesize * 3;
850 csum_bytenr = meta_chunk_start + cfg->nodesize * 4;
852 ret = setup_temp_super(fd, cfg, root_bytenr, chunk_bytenr);
853 if (ret < 0)
854 goto out;
856 ret = setup_temp_root_tree(fd, cfg, root_bytenr, extent_bytenr,
857 dev_bytenr, fs_bytenr, csum_bytenr);
858 if (ret < 0)
859 goto out;
860 ret = setup_temp_chunk_tree(fd, cfg, sys_chunk_start, meta_chunk_start,
861 chunk_bytenr);
862 if (ret < 0)
863 goto out;
864 ret = setup_temp_dev_tree(fd, cfg, sys_chunk_start, meta_chunk_start,
865 dev_bytenr);
866 if (ret < 0)
867 goto out;
868 ret = setup_temp_fs_tree(fd, cfg, fs_bytenr);
869 if (ret < 0)
870 goto out;
871 ret = setup_temp_csum_tree(fd, cfg, csum_bytenr);
872 if (ret < 0)
873 goto out;
875 * Setup extent tree last, since it may need to read tree block key
876 * for non-skinny metadata case.
878 ret = setup_temp_extent_tree(fd, cfg, chunk_bytenr, root_bytenr,
879 extent_bytenr, dev_bytenr, fs_bytenr,
880 csum_bytenr);
881 out:
882 return ret;