2 * Copyright (C) 2008 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
19 #define _XOPEN_SOURCE 500
24 #include <sys/types.h>
30 #include "kerncompat.h"
34 #include "transaction.h"
39 #define HEADER_MAGIC 0xbd5c25e27295668bULL
40 #define MAX_PENDING_SIZE (256 * 1024)
41 #define BLOCK_SIZE 1024
42 #define BLOCK_MASK (BLOCK_SIZE - 1)
44 #define COMPRESS_NONE 0
45 #define COMPRESS_ZLIB 1
47 struct meta_cluster_item {
50 } __attribute__ ((__packed__));
52 struct meta_cluster_header {
57 } __attribute__ ((__packed__));
59 /* cluster header + index items + buffers */
61 struct meta_cluster_header header;
62 struct meta_cluster_item items[];
63 } __attribute__ ((__packed__));
65 #define ITEMS_PER_CLUSTER ((BLOCK_SIZE - sizeof(struct meta_cluster)) / \
66 sizeof(struct meta_cluster_item))
69 struct list_head list;
70 struct list_head ordered;
78 struct metadump_struct {
79 struct btrfs_root *root;
82 struct meta_cluster *cluster;
86 pthread_mutex_t mutex;
89 struct list_head list;
90 struct list_head ordered;
102 struct mdrestore_struct {
108 pthread_mutex_t mutex;
111 struct list_head list;
115 u8 uuid[BTRFS_UUID_SIZE];
116 u8 fsid[BTRFS_FSID_SIZE];
124 static void csum_block(u8 *buf, size_t len)
126 char result[BTRFS_CRC32_SIZE];
128 crc = crc32c(crc, buf + BTRFS_CSUM_SIZE, len - BTRFS_CSUM_SIZE);
129 btrfs_csum_final(crc, result);
130 memcpy(buf, result, BTRFS_CRC32_SIZE);
134 * zero inline extents and csum items
136 static void zero_items(u8 *dst, struct extent_buffer *src)
138 struct btrfs_file_extent_item *fi;
139 struct btrfs_item *item;
140 struct btrfs_key key;
141 u32 nritems = btrfs_header_nritems(src);
146 for (i = 0; i < nritems; i++) {
147 item = btrfs_item_nr(src, i);
148 btrfs_item_key_to_cpu(src, &key, i);
149 if (key.type == BTRFS_CSUM_ITEM_KEY) {
150 size = btrfs_item_size_nr(src, i);
151 memset(dst + btrfs_leaf_data(src) +
152 btrfs_item_offset_nr(src, i), 0, size);
155 if (key.type != BTRFS_EXTENT_DATA_KEY)
158 fi = btrfs_item_ptr(src, i, struct btrfs_file_extent_item);
159 extent_type = btrfs_file_extent_type(src, fi);
160 if (extent_type != BTRFS_FILE_EXTENT_INLINE)
163 ptr = btrfs_file_extent_inline_start(fi);
164 size = btrfs_file_extent_inline_item_len(src, item);
165 memset(dst + ptr, 0, size);
170 * copy buffer and zero useless data in the buffer
172 static void copy_buffer(u8 *dst, struct extent_buffer *src)
178 memcpy(dst, src->data, src->len);
179 if (src->start == BTRFS_SUPER_INFO_OFFSET)
182 level = btrfs_header_level(src);
183 nritems = btrfs_header_nritems(src);
186 size = sizeof(struct btrfs_header);
187 memset(dst + size, 0, src->len - size);
188 } else if (level == 0) {
189 size = btrfs_leaf_data(src) +
190 btrfs_item_offset_nr(src, nritems - 1) -
191 btrfs_item_nr_offset(nritems);
192 memset(dst + btrfs_item_nr_offset(nritems), 0, size);
193 zero_items(dst, src);
195 size = offsetof(struct btrfs_node, ptrs) +
196 sizeof(struct btrfs_key_ptr) * nritems;
197 memset(dst + size, 0, src->len - size);
199 csum_block(dst, src->len);
202 static void *dump_worker(void *data)
204 struct metadump_struct *md = (struct metadump_struct *)data;
205 struct async_work *async;
209 pthread_mutex_lock(&md->mutex);
210 while (list_empty(&md->list)) {
212 pthread_mutex_unlock(&md->mutex);
215 pthread_cond_wait(&md->cond, &md->mutex);
217 async = list_entry(md->list.next, struct async_work, list);
218 list_del_init(&async->list);
219 pthread_mutex_unlock(&md->mutex);
221 if (md->compress_level > 0) {
222 u8 *orig = async->buffer;
224 async->bufsize = compressBound(async->size);
225 async->buffer = malloc(async->bufsize);
227 ret = compress2(async->buffer,
228 (unsigned long *)&async->bufsize,
229 orig, async->size, md->compress_level);
237 pthread_mutex_lock(&md->mutex);
239 pthread_mutex_unlock(&md->mutex);
245 static void meta_cluster_init(struct metadump_struct *md, u64 start)
247 struct meta_cluster_header *header;
251 header = &md->cluster->header;
252 header->magic = cpu_to_le64(HEADER_MAGIC);
253 header->bytenr = cpu_to_le64(start);
254 header->nritems = cpu_to_le32(0);
255 header->compress = md->compress_level > 0 ?
256 COMPRESS_ZLIB : COMPRESS_NONE;
259 static int metadump_init(struct metadump_struct *md, struct btrfs_root *root,
260 FILE *out, int num_threads, int compress_level)
264 memset(md, 0, sizeof(*md));
265 pthread_cond_init(&md->cond, NULL);
266 pthread_mutex_init(&md->mutex, NULL);
267 INIT_LIST_HEAD(&md->list);
268 INIT_LIST_HEAD(&md->ordered);
271 md->pending_start = (u64)-1;
272 md->compress_level = compress_level;
273 md->cluster = calloc(1, BLOCK_SIZE);
275 pthread_cond_destroy(&md->cond);
276 pthread_mutex_destroy(&md->mutex);
280 meta_cluster_init(md, 0);
284 md->num_threads = num_threads;
285 md->threads = calloc(num_threads, sizeof(pthread_t));
288 pthread_cond_destroy(&md->cond);
289 pthread_mutex_destroy(&md->mutex);
293 for (i = 0; i < num_threads; i++) {
294 ret = pthread_create(md->threads + i, NULL, dump_worker, md);
300 pthread_mutex_lock(&md->mutex);
302 pthread_cond_broadcast(&md->cond);
303 pthread_mutex_unlock(&md->mutex);
305 for (i--; i >= 0; i--)
306 pthread_join(md->threads[i], NULL);
308 pthread_cond_destroy(&md->cond);
309 pthread_mutex_destroy(&md->mutex);
317 static void metadump_destroy(struct metadump_struct *md)
320 pthread_mutex_lock(&md->mutex);
322 pthread_cond_broadcast(&md->cond);
323 pthread_mutex_unlock(&md->mutex);
325 for (i = 0; i < md->num_threads; i++)
326 pthread_join(md->threads[i], NULL);
328 pthread_cond_destroy(&md->cond);
329 pthread_mutex_destroy(&md->mutex);
334 static int write_zero(FILE *out, size_t size)
336 static char zero[BLOCK_SIZE];
337 return fwrite(zero, size, 1, out);
340 static int write_buffers(struct metadump_struct *md, u64 *next)
342 struct meta_cluster_header *header = &md->cluster->header;
343 struct meta_cluster_item *item;
344 struct async_work *async;
350 if (list_empty(&md->ordered))
353 /* wait until all buffers are compressed */
354 while (md->num_items > md->num_ready) {
355 struct timespec ts = {
359 pthread_mutex_unlock(&md->mutex);
360 nanosleep(&ts, NULL);
361 pthread_mutex_lock(&md->mutex);
364 /* setup and write index block */
365 list_for_each_entry(async, &md->ordered, ordered) {
366 item = md->cluster->items + nritems;
367 item->bytenr = cpu_to_le64(async->start);
368 item->size = cpu_to_le32(async->bufsize);
371 header->nritems = cpu_to_le32(nritems);
373 ret = fwrite(md->cluster, BLOCK_SIZE, 1, md->out);
375 fprintf(stderr, "Error writing out cluster: %d\n", errno);
380 bytenr += le64_to_cpu(header->bytenr) + BLOCK_SIZE;
381 while (!list_empty(&md->ordered)) {
382 async = list_entry(md->ordered.next, struct async_work,
384 list_del_init(&async->ordered);
386 bytenr += async->bufsize;
388 ret = fwrite(async->buffer, async->bufsize, 1,
393 fprintf(stderr, "Error writing out cluster: %d\n",
401 /* zero unused space in the last block */
402 if (!err && bytenr & BLOCK_MASK) {
403 size_t size = BLOCK_SIZE - (bytenr & BLOCK_MASK);
406 ret = write_zero(md->out, size);
408 fprintf(stderr, "Error zeroing out buffer: %d\n",
418 static int read_data_extent(struct metadump_struct *md,
419 struct async_work *async)
421 struct btrfs_multi_bio *multi = NULL;
422 struct btrfs_device *device;
423 u64 bytes_left = async->size;
424 u64 logical = async->start;
433 read_len = bytes_left;
434 ret = btrfs_map_block(&md->root->fs_info->mapping_tree, READ,
435 logical, &read_len, &multi, 0, NULL);
437 fprintf(stderr, "Couldn't map data block %d\n", ret);
441 device = multi->stripes[0].dev;
443 if (device->fd == 0) {
445 "Device we need to read from is not open\n");
450 bytenr = multi->stripes[0].physical;
453 read_len = min(read_len, bytes_left);
454 done = pread64(fd, async->buffer+offset, read_len, bytenr);
455 if (done < read_len) {
457 fprintf(stderr, "Error reading extent %d\n",
460 fprintf(stderr, "Short read\n");
472 static int flush_pending(struct metadump_struct *md, int done)
474 struct async_work *async = NULL;
475 struct extent_buffer *eb;
476 u64 blocksize = md->root->nodesize;
482 if (md->pending_size) {
483 async = calloc(1, sizeof(*async));
487 async->start = md->pending_start;
488 async->size = md->pending_size;
489 async->bufsize = async->size;
490 async->buffer = malloc(async->bufsize);
491 if (!async->buffer) {
496 start = async->start;
500 ret = read_data_extent(md, async);
508 while (!md->data && size > 0) {
509 eb = read_tree_block(md->root, start, blocksize, 0);
514 "Error reading metadata block\n");
517 copy_buffer(async->buffer + offset, eb);
518 free_extent_buffer(eb);
524 md->pending_start = (u64)-1;
525 md->pending_size = 0;
530 pthread_mutex_lock(&md->mutex);
532 list_add_tail(&async->ordered, &md->ordered);
534 if (md->compress_level > 0) {
535 list_add_tail(&async->list, &md->list);
536 pthread_cond_signal(&md->cond);
541 if (md->num_items >= ITEMS_PER_CLUSTER || done) {
542 ret = write_buffers(md, &start);
544 fprintf(stderr, "Error writing buffers %d\n",
547 meta_cluster_init(md, start);
549 pthread_mutex_unlock(&md->mutex);
553 static int add_extent(u64 start, u64 size, struct metadump_struct *md,
557 if (md->data != data ||
558 md->pending_size + size > MAX_PENDING_SIZE ||
559 md->pending_start + md->pending_size != start) {
560 ret = flush_pending(md, 0);
563 md->pending_start = start;
565 readahead_tree_block(md->root, start, size, 0);
566 md->pending_size += size;
571 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
572 static int is_tree_block(struct btrfs_root *extent_root,
573 struct btrfs_path *path, u64 bytenr)
575 struct extent_buffer *leaf;
576 struct btrfs_key key;
580 leaf = path->nodes[0];
582 struct btrfs_extent_ref_v0 *ref_item;
584 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
585 ret = btrfs_next_leaf(extent_root, path);
590 leaf = path->nodes[0];
592 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
593 if (key.objectid != bytenr)
595 if (key.type != BTRFS_EXTENT_REF_V0_KEY)
597 ref_item = btrfs_item_ptr(leaf, path->slots[0],
598 struct btrfs_extent_ref_v0);
599 ref_objectid = btrfs_ref_objectid_v0(leaf, ref_item);
600 if (ref_objectid < BTRFS_FIRST_FREE_OBJECTID)
608 static int copy_log_blocks(struct btrfs_root *root, struct extent_buffer *eb,
609 struct metadump_struct *metadump,
612 struct extent_buffer *tmp;
613 struct btrfs_root_item *ri;
614 struct btrfs_key key;
621 ret = add_extent(btrfs_header_bytenr(eb), root->leafsize, metadump, 0);
623 fprintf(stderr, "Error adding metadata block\n");
627 if (btrfs_header_level(eb) == 0 && !log_root_tree)
630 level = btrfs_header_level(eb);
631 nritems = btrfs_header_nritems(eb);
632 for (i = 0; i < nritems; i++) {
634 btrfs_item_key_to_cpu(eb, &key, i);
635 if (key.type != BTRFS_ROOT_ITEM_KEY)
637 ri = btrfs_item_ptr(eb, i, struct btrfs_root_item);
638 bytenr = btrfs_disk_root_bytenr(eb, ri);
639 tmp = read_tree_block(root, bytenr, root->leafsize, 0);
642 "Error reading log root block\n");
645 ret = copy_log_blocks(root, tmp, metadump, 0);
646 free_extent_buffer(tmp);
650 bytenr = btrfs_node_blockptr(eb, i);
651 tmp = read_tree_block(root, bytenr, root->leafsize, 0);
653 fprintf(stderr, "Error reading log block\n");
656 ret = copy_log_blocks(root, tmp, metadump,
658 free_extent_buffer(tmp);
667 static int copy_log_trees(struct btrfs_root *root,
668 struct metadump_struct *metadump,
669 struct btrfs_path *path)
671 u64 blocknr = btrfs_super_log_root(root->fs_info->super_copy);
676 if (!root->fs_info->log_root_tree ||
677 !root->fs_info->log_root_tree->node) {
678 fprintf(stderr, "Error copying tree log, it wasn't setup\n");
682 return copy_log_blocks(root, root->fs_info->log_root_tree->node,
686 static int copy_space_cache(struct btrfs_root *root,
687 struct metadump_struct *metadump,
688 struct btrfs_path *path)
690 struct extent_buffer *leaf;
691 struct btrfs_file_extent_item *fi;
692 struct btrfs_key key;
693 u64 bytenr, num_bytes;
696 root = root->fs_info->tree_root;
699 key.type = BTRFS_EXTENT_DATA_KEY;
702 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
704 fprintf(stderr, "Error searching for free space inode %d\n",
710 leaf = path->nodes[0];
711 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
712 ret = btrfs_next_leaf(root, path);
714 fprintf(stderr, "Error going to next leaf "
720 leaf = path->nodes[0];
723 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
724 if (key.type != BTRFS_EXTENT_DATA_KEY) {
729 fi = btrfs_item_ptr(leaf, path->slots[0],
730 struct btrfs_file_extent_item);
731 if (btrfs_file_extent_type(leaf, fi) !=
732 BTRFS_FILE_EXTENT_REG) {
737 bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
738 num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
739 ret = add_extent(bytenr, num_bytes, metadump, 1);
741 fprintf(stderr, "Error adding space cache blocks %d\n",
743 btrfs_release_path(root, path);
752 static int create_metadump(const char *input, FILE *out, int num_threads,
755 struct btrfs_root *root;
756 struct btrfs_root *extent_root;
757 struct btrfs_path *path = NULL;
758 struct extent_buffer *leaf;
759 struct btrfs_extent_item *ei;
760 struct btrfs_key key;
761 struct metadump_struct metadump;
767 root = open_ctree(input, 0, 0);
769 fprintf(stderr, "Open ctree failed\n");
773 BUG_ON(root->nodesize != root->leafsize);
775 ret = metadump_init(&metadump, root, out, num_threads,
778 fprintf(stderr, "Error initing metadump %d\n", ret);
783 ret = add_extent(BTRFS_SUPER_INFO_OFFSET, 4096, &metadump, 0);
785 fprintf(stderr, "Error adding metadata %d\n", ret);
790 extent_root = root->fs_info->extent_root;
791 path = btrfs_alloc_path();
793 fprintf(stderr, "Out of memory allocing path\n");
797 bytenr = BTRFS_SUPER_INFO_OFFSET + 4096;
798 key.objectid = bytenr;
799 key.type = BTRFS_EXTENT_ITEM_KEY;
802 ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
804 fprintf(stderr, "Error searching extent root %d\n", ret);
810 leaf = path->nodes[0];
811 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
812 ret = btrfs_next_leaf(extent_root, path);
814 fprintf(stderr, "Error going to next leaf %d"
821 leaf = path->nodes[0];
824 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
825 if (key.objectid < bytenr ||
826 key.type != BTRFS_EXTENT_ITEM_KEY) {
831 bytenr = key.objectid;
832 num_bytes = key.offset;
834 if (btrfs_item_size_nr(leaf, path->slots[0]) > sizeof(*ei)) {
835 ei = btrfs_item_ptr(leaf, path->slots[0],
836 struct btrfs_extent_item);
837 if (btrfs_extent_flags(leaf, ei) &
838 BTRFS_EXTENT_FLAG_TREE_BLOCK) {
839 ret = add_extent(bytenr, num_bytes, &metadump,
842 fprintf(stderr, "Error adding block "
849 #ifdef BTRFS_COMPAT_EXTENT_TREE_V0
850 ret = is_tree_block(extent_root, path, bytenr);
852 fprintf(stderr, "Error checking tree block "
859 ret = add_extent(bytenr, num_bytes, &metadump,
862 fprintf(stderr, "Error adding block "
869 fprintf(stderr, "Either extent tree corruption or "
870 "you haven't built with V0 support\n");
878 btrfs_release_path(root, path);
880 ret = copy_log_trees(root, &metadump, path);
886 ret = copy_space_cache(root, &metadump, path);
888 ret = flush_pending(&metadump, 1);
892 fprintf(stderr, "Error flushing pending %d\n", ret);
895 metadump_destroy(&metadump);
897 btrfs_free_path(path);
898 ret = close_ctree(root);
899 return err ? err : ret;
902 static void update_super_old(u8 *buffer)
904 struct btrfs_super_block *super = (struct btrfs_super_block *)buffer;
905 struct btrfs_chunk *chunk;
906 struct btrfs_disk_key *key;
907 u32 sectorsize = btrfs_super_sectorsize(super);
908 u64 flags = btrfs_super_flags(super);
910 flags |= BTRFS_SUPER_FLAG_METADUMP;
911 btrfs_set_super_flags(super, flags);
913 key = (struct btrfs_disk_key *)(super->sys_chunk_array);
914 chunk = (struct btrfs_chunk *)(super->sys_chunk_array +
915 sizeof(struct btrfs_disk_key));
917 btrfs_set_disk_key_objectid(key, BTRFS_FIRST_CHUNK_TREE_OBJECTID);
918 btrfs_set_disk_key_type(key, BTRFS_CHUNK_ITEM_KEY);
919 btrfs_set_disk_key_offset(key, 0);
921 btrfs_set_stack_chunk_length(chunk, (u64)-1);
922 btrfs_set_stack_chunk_owner(chunk, BTRFS_EXTENT_TREE_OBJECTID);
923 btrfs_set_stack_chunk_stripe_len(chunk, 64 * 1024);
924 btrfs_set_stack_chunk_type(chunk, BTRFS_BLOCK_GROUP_SYSTEM);
925 btrfs_set_stack_chunk_io_align(chunk, sectorsize);
926 btrfs_set_stack_chunk_io_width(chunk, sectorsize);
927 btrfs_set_stack_chunk_sector_size(chunk, sectorsize);
928 btrfs_set_stack_chunk_num_stripes(chunk, 1);
929 btrfs_set_stack_chunk_sub_stripes(chunk, 0);
930 chunk->stripe.devid = super->dev_item.devid;
931 chunk->stripe.offset = cpu_to_le64(0);
932 memcpy(chunk->stripe.dev_uuid, super->dev_item.uuid, BTRFS_UUID_SIZE);
933 btrfs_set_super_sys_array_size(super, sizeof(*key) + sizeof(*chunk));
934 csum_block(buffer, 4096);
937 static int update_super(u8 *buffer)
939 struct btrfs_super_block *super = (struct btrfs_super_block *)buffer;
940 struct btrfs_chunk *chunk;
941 struct btrfs_disk_key *disk_key;
942 struct btrfs_key key;
943 u32 new_array_size = 0;
950 write_ptr = ptr = super->sys_chunk_array;
951 array_size = btrfs_super_sys_array_size(super);
953 while (cur < array_size) {
954 disk_key = (struct btrfs_disk_key *)ptr;
955 btrfs_disk_key_to_cpu(&key, disk_key);
957 new_array_size += sizeof(*disk_key);
958 memmove(write_ptr, ptr, sizeof(*disk_key));
960 write_ptr += sizeof(*disk_key);
961 ptr += sizeof(*disk_key);
962 cur += sizeof(*disk_key);
963 new_cur += sizeof(*disk_key);
965 if (key.type == BTRFS_CHUNK_ITEM_KEY) {
966 chunk = (struct btrfs_chunk *)ptr;
967 old_num_stripes = btrfs_stack_chunk_num_stripes(chunk);
968 chunk = (struct btrfs_chunk *)write_ptr;
970 memmove(write_ptr, ptr, sizeof(*chunk));
971 btrfs_set_stack_chunk_num_stripes(chunk, 1);
972 btrfs_set_stack_chunk_sub_stripes(chunk, 0);
973 btrfs_set_stack_chunk_type(chunk,
974 BTRFS_BLOCK_GROUP_SYSTEM);
975 chunk->stripe.devid = super->dev_item.devid;
976 chunk->stripe.offset = cpu_to_le64(key.offset);
977 memcpy(chunk->stripe.dev_uuid, super->dev_item.uuid,
979 new_array_size += sizeof(*chunk);
980 new_cur += sizeof(*chunk);
982 fprintf(stderr, "Bogus key in the sys chunk array "
986 write_ptr += sizeof(*chunk);
987 ptr += btrfs_chunk_item_size(old_num_stripes);
988 cur += btrfs_chunk_item_size(old_num_stripes);
991 btrfs_set_super_sys_array_size(super, new_array_size);
992 csum_block(buffer, 4096);
997 static struct extent_buffer *alloc_dummy_eb(u64 bytenr, u32 size)
999 struct extent_buffer *eb;
1001 eb = malloc(sizeof(struct extent_buffer) + size);
1004 memset(eb, 0, sizeof(struct extent_buffer) + size);
1011 static void truncate_item(struct extent_buffer *eb, int slot, u32 new_size)
1013 struct btrfs_item *item;
1021 old_size = btrfs_item_size_nr(eb, slot);
1022 if (old_size == new_size)
1025 nritems = btrfs_header_nritems(eb);
1026 data_end = btrfs_item_offset_nr(eb, nritems - 1);
1028 old_data_start = btrfs_item_offset_nr(eb, slot);
1029 size_diff = old_size - new_size;
1031 for (i = slot; i < nritems; i++) {
1033 item = btrfs_item_nr(eb, i);
1034 ioff = btrfs_item_offset(eb, item);
1035 btrfs_set_item_offset(eb, item, ioff + size_diff);
1038 memmove_extent_buffer(eb, btrfs_leaf_data(eb) + data_end + size_diff,
1039 btrfs_leaf_data(eb) + data_end,
1040 old_data_start + new_size - data_end);
1041 item = btrfs_item_nr(eb, slot);
1042 btrfs_set_item_size(eb, item, new_size);
1045 static int fixup_chunk_tree_block(struct mdrestore_struct *mdres,
1046 struct async_work *async, u8 *buffer,
1049 struct extent_buffer *eb;
1050 size_t size_left = size;
1051 u64 bytenr = async->start;
1054 if (size_left % mdres->leafsize)
1057 eb = alloc_dummy_eb(bytenr, mdres->leafsize);
1063 memcpy(eb->data, buffer, mdres->leafsize);
1065 if (btrfs_header_bytenr(eb) != bytenr)
1067 if (memcmp(mdres->fsid,
1068 eb->data + offsetof(struct btrfs_header, fsid),
1072 if (btrfs_header_owner(eb) != BTRFS_CHUNK_TREE_OBJECTID)
1075 if (btrfs_header_level(eb) != 0)
1078 for (i = 0; i < btrfs_header_nritems(eb); i++) {
1079 struct btrfs_chunk chunk;
1080 struct btrfs_key key;
1083 btrfs_item_key_to_cpu(eb, &key, i);
1084 if (key.type != BTRFS_CHUNK_ITEM_KEY)
1086 truncate_item(eb, i, sizeof(chunk));
1087 read_extent_buffer(eb, &chunk,
1088 btrfs_item_ptr_offset(eb, i),
1091 /* Zero out the RAID profile */
1092 type = btrfs_stack_chunk_type(&chunk);
1093 type &= (BTRFS_BLOCK_GROUP_DATA |
1094 BTRFS_BLOCK_GROUP_SYSTEM |
1095 BTRFS_BLOCK_GROUP_METADATA);
1096 btrfs_set_stack_chunk_type(&chunk, type);
1098 btrfs_set_stack_chunk_num_stripes(&chunk, 1);
1099 btrfs_set_stack_chunk_sub_stripes(&chunk, 0);
1100 btrfs_set_stack_stripe_devid(&chunk.stripe, mdres->devid);
1101 btrfs_set_stack_stripe_offset(&chunk.stripe, key.offset);
1102 memcpy(chunk.stripe.dev_uuid, mdres->uuid,
1104 write_extent_buffer(eb, &chunk,
1105 btrfs_item_ptr_offset(eb, i),
1108 memcpy(buffer, eb->data, eb->len);
1109 csum_block(buffer, eb->len);
1111 size_left -= mdres->leafsize;
1112 buffer += mdres->leafsize;
1113 bytenr += mdres->leafsize;
1119 static void write_backup_supers(int fd, u8 *buf)
1127 if (fstat(fd, &st)) {
1128 fprintf(stderr, "Couldn't stat restore point, won't be able "
1129 "to write backup supers: %d\n", errno);
1133 size = btrfs_device_size(fd, &st);
1135 for (i = 1; i < BTRFS_SUPER_MIRROR_MAX; i++) {
1136 bytenr = btrfs_sb_offset(i);
1137 if (bytenr + 4096 > size)
1139 ret = pwrite64(fd, buf, 4096, bytenr);
1142 fprintf(stderr, "Problem writing out backup "
1143 "super block %d, err %d\n", i, errno);
1145 fprintf(stderr, "Short write writing out "
1146 "backup super block\n");
1152 static void *restore_worker(void *data)
1154 struct mdrestore_struct *mdres = (struct mdrestore_struct *)data;
1155 struct async_work *async;
1162 outfd = fileno(mdres->out);
1163 buffer = malloc(MAX_PENDING_SIZE * 2);
1165 fprintf(stderr, "Error allocing buffer\n");
1166 pthread_mutex_lock(&mdres->mutex);
1168 mdres->error = -ENOMEM;
1169 pthread_mutex_unlock(&mdres->mutex);
1176 pthread_mutex_lock(&mdres->mutex);
1177 while (!mdres->leafsize || list_empty(&mdres->list)) {
1179 pthread_mutex_unlock(&mdres->mutex);
1182 pthread_cond_wait(&mdres->cond, &mdres->mutex);
1184 async = list_entry(mdres->list.next, struct async_work, list);
1185 list_del_init(&async->list);
1186 pthread_mutex_unlock(&mdres->mutex);
1188 if (mdres->compress_method == COMPRESS_ZLIB) {
1189 size = MAX_PENDING_SIZE * 2;
1190 ret = uncompress(buffer, (unsigned long *)&size,
1191 async->buffer, async->bufsize);
1193 fprintf(stderr, "Error decompressing %d\n",
1199 outbuf = async->buffer;
1200 size = async->bufsize;
1203 if (async->start == BTRFS_SUPER_INFO_OFFSET) {
1204 if (mdres->old_restore) {
1205 update_super_old(outbuf);
1207 ret = update_super(outbuf);
1211 } else if (!mdres->old_restore) {
1212 ret = fixup_chunk_tree_block(mdres, async, outbuf, size);
1217 ret = pwrite64(outfd, outbuf, size, async->start);
1220 fprintf(stderr, "Error writing to device %d\n",
1224 fprintf(stderr, "Short write\n");
1229 if (async->start == BTRFS_SUPER_INFO_OFFSET)
1230 write_backup_supers(outfd, outbuf);
1232 pthread_mutex_lock(&mdres->mutex);
1233 if (err && !mdres->error)
1236 pthread_mutex_unlock(&mdres->mutex);
1238 free(async->buffer);
1246 static void mdrestore_destroy(struct mdrestore_struct *mdres)
1249 pthread_mutex_lock(&mdres->mutex);
1251 pthread_cond_broadcast(&mdres->cond);
1252 pthread_mutex_unlock(&mdres->mutex);
1254 for (i = 0; i < mdres->num_threads; i++)
1255 pthread_join(mdres->threads[i], NULL);
1257 pthread_cond_destroy(&mdres->cond);
1258 pthread_mutex_destroy(&mdres->mutex);
1259 free(mdres->threads);
1262 static int mdrestore_init(struct mdrestore_struct *mdres,
1263 FILE *in, FILE *out, int old_restore,
1268 memset(mdres, 0, sizeof(*mdres));
1269 pthread_cond_init(&mdres->cond, NULL);
1270 pthread_mutex_init(&mdres->mutex, NULL);
1271 INIT_LIST_HEAD(&mdres->list);
1274 mdres->old_restore = old_restore;
1279 mdres->num_threads = num_threads;
1280 mdres->threads = calloc(num_threads, sizeof(pthread_t));
1281 if (!mdres->threads)
1283 for (i = 0; i < num_threads; i++) {
1284 ret = pthread_create(mdres->threads + i, NULL, restore_worker,
1290 mdrestore_destroy(mdres);
1294 static int fill_mdres_info(struct mdrestore_struct *mdres,
1295 struct async_work *async)
1297 struct btrfs_super_block *super;
1302 if (mdres->compress_method == COMPRESS_ZLIB) {
1303 size_t size = MAX_PENDING_SIZE * 2;
1305 buffer = malloc(MAX_PENDING_SIZE * 2);
1308 ret = uncompress(buffer, (unsigned long *)&size,
1309 async->buffer, async->bufsize);
1311 fprintf(stderr, "Error decompressing %d\n", ret);
1317 outbuf = async->buffer;
1320 super = (struct btrfs_super_block *)outbuf;
1321 mdres->leafsize = btrfs_super_leafsize(super);
1322 memcpy(mdres->fsid, super->fsid, BTRFS_FSID_SIZE);
1323 memcpy(mdres->uuid, super->dev_item.uuid,
1325 mdres->devid = le64_to_cpu(super->dev_item.devid);
1330 static int add_cluster(struct meta_cluster *cluster,
1331 struct mdrestore_struct *mdres, u64 *next)
1333 struct meta_cluster_item *item;
1334 struct meta_cluster_header *header = &cluster->header;
1335 struct async_work *async;
1340 BUG_ON(mdres->num_items);
1341 mdres->compress_method = header->compress;
1343 bytenr = le64_to_cpu(header->bytenr) + BLOCK_SIZE;
1344 nritems = le32_to_cpu(header->nritems);
1345 for (i = 0; i < nritems; i++) {
1346 item = &cluster->items[i];
1347 async = calloc(1, sizeof(*async));
1349 fprintf(stderr, "Error allocating async\n");
1352 async->start = le64_to_cpu(item->bytenr);
1353 async->bufsize = le32_to_cpu(item->size);
1354 async->buffer = malloc(async->bufsize);
1355 if (!async->buffer) {
1356 fprintf(stderr, "Error allocing async buffer\n");
1360 ret = fread(async->buffer, async->bufsize, 1, mdres->in);
1362 fprintf(stderr, "Error reading buffer %d\n", errno);
1363 free(async->buffer);
1367 bytenr += async->bufsize;
1369 pthread_mutex_lock(&mdres->mutex);
1370 if (async->start == BTRFS_SUPER_INFO_OFFSET) {
1371 ret = fill_mdres_info(mdres, async);
1373 fprintf(stderr, "Error setting up restore\n");
1374 pthread_mutex_unlock(&mdres->mutex);
1375 free(async->buffer);
1380 list_add_tail(&async->list, &mdres->list);
1382 pthread_cond_signal(&mdres->cond);
1383 pthread_mutex_unlock(&mdres->mutex);
1385 if (bytenr & BLOCK_MASK) {
1386 char buffer[BLOCK_MASK];
1387 size_t size = BLOCK_SIZE - (bytenr & BLOCK_MASK);
1390 ret = fread(buffer, size, 1, mdres->in);
1392 fprintf(stderr, "Error reading in buffer %d\n", errno);
1400 static int wait_for_worker(struct mdrestore_struct *mdres)
1404 pthread_mutex_lock(&mdres->mutex);
1406 while (!ret && mdres->num_items > 0) {
1407 struct timespec ts = {
1409 .tv_nsec = 10000000,
1411 pthread_mutex_unlock(&mdres->mutex);
1412 nanosleep(&ts, NULL);
1413 pthread_mutex_lock(&mdres->mutex);
1416 pthread_mutex_unlock(&mdres->mutex);
1420 static int restore_metadump(const char *input, FILE *out, int old_restore,
1423 struct meta_cluster *cluster = NULL;
1424 struct meta_cluster_header *header;
1425 struct mdrestore_struct mdrestore;
1430 if (!strcmp(input, "-")) {
1433 in = fopen(input, "r");
1435 perror("unable to open metadump image");
1440 cluster = malloc(BLOCK_SIZE);
1442 fprintf(stderr, "Error allocating cluster\n");
1448 ret = mdrestore_init(&mdrestore, in, out, old_restore, num_threads);
1450 fprintf(stderr, "Error initing mdrestore %d\n", ret);
1458 ret = fread(cluster, BLOCK_SIZE, 1, in);
1462 header = &cluster->header;
1463 if (le64_to_cpu(header->magic) != HEADER_MAGIC ||
1464 le64_to_cpu(header->bytenr) != bytenr) {
1465 fprintf(stderr, "bad header in metadump image\n");
1469 ret = add_cluster(cluster, &mdrestore, &bytenr);
1471 fprintf(stderr, "Error adding cluster\n");
1475 ret = wait_for_worker(&mdrestore);
1477 fprintf(stderr, "One of the threads errored out %d\n",
1483 mdrestore_destroy(&mdrestore);
1490 static void print_usage(void)
1492 fprintf(stderr, "usage: btrfs-image [options] source target\n");
1493 fprintf(stderr, "\t-r \trestore metadump image\n");
1494 fprintf(stderr, "\t-c value\tcompression level (0 ~ 9)\n");
1495 fprintf(stderr, "\t-t value\tnumber of threads (1 ~ 32)\n");
1496 fprintf(stderr, "\t-o \tdon't mess with the chunk tree when restoring\n");
1500 int main(int argc, char *argv[])
1504 int num_threads = 0;
1505 int compress_level = 0;
1507 int old_restore = 0;
1512 int c = getopt(argc, argv, "rc:t:o");
1520 num_threads = atoi(optarg);
1521 if (num_threads <= 0 || num_threads > 32)
1525 compress_level = atoi(optarg);
1526 if (compress_level < 0 || compress_level > 9)
1537 if (old_restore && create)
1540 argc = argc - optind;
1543 source = argv[optind];
1544 target = argv[optind + 1];
1546 if (create && !strcmp(target, "-")) {
1549 out = fopen(target, "w+");
1551 perror("unable to create target file");
1556 if (num_threads == 0 && compress_level > 0) {
1557 num_threads = sysconf(_SC_NPROCESSORS_ONLN);
1558 if (num_threads <= 0)
1563 ret = create_metadump(source, out, num_threads,
1566 ret = restore_metadump(source, out, old_restore, 1);