2 * Copyright (C) 2011 Red Hat. 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
22 #include "kerncompat.h"
34 #include "print-tree.h"
35 #include "transaction.h"
41 static char path_name
[4096];
42 static int get_snaps
= 0;
43 static int verbose
= 0;
44 static int ignore_errors
= 0;
45 static int overwrite
= 0;
47 static int decompress(char *inbuf
, char *outbuf
, u64 compress_len
,
53 memset(&strm
, 0, sizeof(strm
));
54 ret
= inflateInit(&strm
);
56 fprintf(stderr
, "inflate init returnd %d\n", ret
);
60 strm
.avail_in
= compress_len
;
61 strm
.next_in
= (unsigned char *)inbuf
;
62 strm
.avail_out
= decompress_len
;
63 strm
.next_out
= (unsigned char *)outbuf
;
64 ret
= inflate(&strm
, Z_NO_FLUSH
);
65 if (ret
!= Z_STREAM_END
) {
66 (void)inflateEnd(&strm
);
67 fprintf(stderr
, "ret is %d\n", ret
);
71 (void)inflateEnd(&strm
);
75 int next_leaf(struct btrfs_root
*root
, struct btrfs_path
*path
)
79 struct extent_buffer
*c
;
80 struct extent_buffer
*next
= NULL
;
82 for (; level
< BTRFS_MAX_LEVEL
; level
++) {
83 if (path
->nodes
[level
])
87 if (level
== BTRFS_MAX_LEVEL
)
90 slot
= path
->slots
[level
] + 1;
92 while(level
< BTRFS_MAX_LEVEL
) {
93 if (!path
->nodes
[level
])
96 slot
= path
->slots
[level
] + 1;
97 c
= path
->nodes
[level
];
98 if (slot
>= btrfs_header_nritems(c
)) {
100 if (level
== BTRFS_MAX_LEVEL
)
106 free_extent_buffer(next
);
109 reada_for_search(root
, path
, level
, slot
, 0);
111 next
= read_node_slot(root
, c
, slot
);
114 path
->slots
[level
] = slot
;
117 c
= path
->nodes
[level
];
118 free_extent_buffer(c
);
119 path
->nodes
[level
] = next
;
120 path
->slots
[level
] = 0;
124 reada_for_search(root
, path
, level
, 0, 0);
125 next
= read_node_slot(root
, next
, 0);
130 static int copy_one_inline(int fd
, struct btrfs_path
*path
, u64 pos
)
132 struct extent_buffer
*leaf
= path
->nodes
[0];
133 struct btrfs_file_extent_item
*fi
;
143 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
144 struct btrfs_file_extent_item
);
145 ptr
= btrfs_file_extent_inline_start(fi
);
146 len
= btrfs_file_extent_inline_item_len(leaf
,
147 btrfs_item_nr(leaf
, path
->slots
[0]));
148 read_extent_buffer(leaf
, buf
, ptr
, len
);
150 compress
= btrfs_file_extent_compression(leaf
, fi
);
151 if (compress
== BTRFS_COMPRESS_NONE
) {
152 done
= pwrite(fd
, buf
, len
, pos
);
154 fprintf(stderr
, "Short inline write, wanted %d, did "
155 "%zd: %d\n", len
, done
, errno
);
161 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
162 outbuf
= malloc(ram_size
);
164 fprintf(stderr
, "No memory\n");
168 ret
= decompress(buf
, outbuf
, len
, ram_size
);
174 done
= pwrite(fd
, outbuf
, ram_size
, pos
);
177 fprintf(stderr
, "Short compressed inline write, wanted %d, "
178 "did %zd: %d\n", ram_size
, done
, errno
);
185 static int copy_one_extent(struct btrfs_root
*root
, int fd
,
186 struct extent_buffer
*leaf
,
187 struct btrfs_file_extent_item
*fi
, u64 pos
)
189 struct btrfs_multi_bio
*multi
= NULL
;
190 struct btrfs_device
*device
;
191 char *inbuf
, *outbuf
= NULL
;
192 ssize_t done
, total
= 0;
204 compress
= btrfs_file_extent_compression(leaf
, fi
);
205 bytenr
= btrfs_file_extent_disk_bytenr(leaf
, fi
);
206 disk_size
= btrfs_file_extent_disk_num_bytes(leaf
, fi
);
207 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
208 size_left
= disk_size
;
210 /* we found a hole */
214 inbuf
= malloc(disk_size
);
216 fprintf(stderr
, "No memory\n");
220 if (compress
!= BTRFS_COMPRESS_NONE
) {
221 outbuf
= malloc(ram_size
);
223 fprintf(stderr
, "No memory\n");
230 ret
= btrfs_map_block(&root
->fs_info
->mapping_tree
, READ
,
231 bytenr
, &length
, &multi
, 0);
235 fprintf(stderr
, "Error mapping block %d\n", ret
);
238 device
= multi
->stripes
[0].dev
;
241 dev_bytenr
= multi
->stripes
[0].physical
;
244 if (size_left
< length
)
248 done
= pread(dev_fd
, inbuf
+count
, length
, dev_bytenr
);
252 fprintf(stderr
, "Short read %d\n", errno
);
262 if (compress
== BTRFS_COMPRESS_NONE
) {
263 while (total
< ram_size
) {
264 done
= pwrite(fd
, inbuf
+total
, ram_size
-total
,
268 fprintf(stderr
, "Error writing: %d %s\n", errno
, strerror(errno
));
277 ret
= decompress(inbuf
, outbuf
, disk_size
, ram_size
);
284 while (total
< ram_size
) {
285 done
= pwrite(fd
, outbuf
+total
, ram_size
-total
, pos
+total
);
288 fprintf(stderr
, "Error writing: %d %s\n", errno
, strerror(errno
));
298 static int ask_to_continue(const char *file
)
303 printf("We seem to be looping a lot on %s, do you want to keep going "
304 "on ? (y/N): ", file
);
306 ret
= fgets(buf
, 2, stdin
);
307 if (*ret
== '\n' || tolower(*ret
) == 'n')
309 if (tolower(*ret
) != 'y') {
310 printf("Please enter either 'y' or 'n': ");
318 static int copy_file(struct btrfs_root
*root
, int fd
, struct btrfs_key
*key
,
321 struct extent_buffer
*leaf
;
322 struct btrfs_path
*path
;
323 struct btrfs_file_extent_item
*fi
;
324 struct btrfs_inode_item
*inode_item
;
325 struct btrfs_key found_key
;
332 path
= btrfs_alloc_path();
334 fprintf(stderr
, "Ran out of memory\n");
337 path
->skip_locking
= 1;
339 ret
= btrfs_lookup_inode(NULL
, root
, path
, key
, 0);
341 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
342 struct btrfs_inode_item
);
343 found_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
345 btrfs_release_path(root
, path
);
348 key
->type
= BTRFS_EXTENT_DATA_KEY
;
350 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
352 fprintf(stderr
, "Error searching %d\n", ret
);
353 btrfs_free_path(path
);
357 leaf
= path
->nodes
[0];
359 ret
= next_leaf(root
, path
);
361 fprintf(stderr
, "Error getting next leaf %d\n",
363 btrfs_free_path(path
);
365 } else if (ret
> 0) {
366 /* No more leaves to search */
367 btrfs_free_path(path
);
370 leaf
= path
->nodes
[0];
374 if (loops
++ >= 1024) {
375 ret
= ask_to_continue(file
);
380 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
382 ret
= next_leaf(root
, path
);
384 fprintf(stderr
, "Error searching %d\n", ret
);
385 btrfs_free_path(path
);
388 /* No more leaves to search */
389 btrfs_free_path(path
);
392 leaf
= path
->nodes
[0];
396 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
397 if (found_key
.objectid
!= key
->objectid
)
399 if (found_key
.type
!= key
->type
)
401 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
402 struct btrfs_file_extent_item
);
403 extent_type
= btrfs_file_extent_type(leaf
, fi
);
404 compression
= btrfs_file_extent_compression(leaf
, fi
);
405 if (compression
>= BTRFS_COMPRESS_LAST
) {
406 fprintf(stderr
, "Don't support compression yet %d\n",
408 btrfs_free_path(path
);
412 if (extent_type
== BTRFS_FILE_EXTENT_PREALLOC
)
414 if (extent_type
== BTRFS_FILE_EXTENT_INLINE
) {
415 ret
= copy_one_inline(fd
, path
, found_key
.offset
);
417 btrfs_free_path(path
);
420 } else if (extent_type
== BTRFS_FILE_EXTENT_REG
) {
421 ret
= copy_one_extent(root
, fd
, leaf
, fi
,
424 btrfs_free_path(path
);
428 printf("Weird extent type %d\n", extent_type
);
434 btrfs_free_path(path
);
437 ret
= ftruncate(fd
, (loff_t
)found_size
);
444 static int search_dir(struct btrfs_root
*root
, struct btrfs_key
*key
,
447 struct btrfs_path
*path
;
448 struct extent_buffer
*leaf
;
449 struct btrfs_dir_item
*dir_item
;
450 struct btrfs_key found_key
, location
;
451 char filename
[BTRFS_NAME_LEN
+ 1];
452 unsigned long name_ptr
;
459 path
= btrfs_alloc_path();
461 fprintf(stderr
, "Ran out of memory\n");
464 path
->skip_locking
= 1;
467 key
->type
= BTRFS_DIR_INDEX_KEY
;
469 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
471 fprintf(stderr
, "Error searching %d\n", ret
);
472 btrfs_free_path(path
);
476 leaf
= path
->nodes
[0];
479 printf("No leaf after search, looking for the next "
481 ret
= next_leaf(root
, path
);
483 fprintf(stderr
, "Error getting next leaf %d\n",
485 btrfs_free_path(path
);
487 } else if (ret
> 0) {
488 /* No more leaves to search */
490 printf("Reached the end of the tree looking "
491 "for the directory\n");
492 btrfs_free_path(path
);
495 leaf
= path
->nodes
[0];
499 if (loops
++ >= 1024) {
500 printf("We have looped trying to restore files in %s "
501 "too many times to be making progress, "
506 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
508 ret
= next_leaf(root
, path
);
510 fprintf(stderr
, "Error searching %d\n",
512 btrfs_free_path(path
);
514 } else if (ret
> 0) {
515 /* No more leaves to search */
517 printf("Reached the end of "
518 "the tree searching the"
520 btrfs_free_path(path
);
523 leaf
= path
->nodes
[0];
527 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
528 if (found_key
.objectid
!= key
->objectid
) {
530 printf("Found objectid=%Lu, key=%Lu\n",
531 found_key
.objectid
, key
->objectid
);
534 if (found_key
.type
!= key
->type
) {
536 printf("Found type=%u, want=%u\n",
537 found_key
.type
, key
->type
);
540 dir_item
= btrfs_item_ptr(leaf
, path
->slots
[0],
541 struct btrfs_dir_item
);
542 name_ptr
= (unsigned long)(dir_item
+ 1);
543 name_len
= btrfs_dir_name_len(leaf
, dir_item
);
544 read_extent_buffer(leaf
, filename
, name_ptr
, name_len
);
545 filename
[name_len
] = '\0';
546 type
= btrfs_dir_type(leaf
, dir_item
);
547 btrfs_dir_item_key_to_cpu(leaf
, dir_item
, &location
);
549 snprintf(path_name
, 4096, "%s/%s", dir
, filename
);
553 * At this point we're only going to restore directories and
554 * files, no symlinks or anything else.
556 if (type
== BTRFS_FT_REG_FILE
) {
561 ret
= stat(path_name
, &st
);
564 if (verbose
|| !warn
)
565 printf("Skipping existing file"
569 printf("If you wish to overwrite use "
570 "the -o option to overwrite\n");
577 printf("Restoring %s\n", path_name
);
578 fd
= open(path_name
, O_CREAT
|O_WRONLY
, 0644);
580 fprintf(stderr
, "Error creating %s: %d\n",
584 btrfs_free_path(path
);
588 ret
= copy_file(root
, fd
, &location
, path_name
);
593 btrfs_free_path(path
);
596 } else if (type
== BTRFS_FT_DIR
) {
597 struct btrfs_root
*search_root
= root
;
598 char *dir
= strdup(path_name
);
601 fprintf(stderr
, "Ran out of memory\n");
602 btrfs_free_path(path
);
606 if (location
.type
== BTRFS_ROOT_ITEM_KEY
) {
608 * If we are a snapshot and this is the index
609 * object to ourselves just skip it.
611 if (location
.objectid
==
612 root
->root_key
.objectid
) {
617 search_root
= btrfs_read_fs_root(root
->fs_info
,
619 if (IS_ERR(search_root
)) {
621 fprintf(stderr
, "Error reading "
622 "subvolume %s: %lu\n",
624 PTR_ERR(search_root
));
627 return PTR_ERR(search_root
);
631 * A subvolume will have a key.offset of 0, a
632 * snapshot will have key.offset of a transid.
634 if (search_root
->root_key
.offset
!= 0 &&
637 printf("Skipping snapshot %s\n",
641 location
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
645 printf("Restoring %s\n", path_name
);
648 ret
= mkdir(path_name
, 0755);
649 if (ret
&& errno
!= EEXIST
) {
651 fprintf(stderr
, "Error mkdiring %s: %d\n",
655 btrfs_free_path(path
);
659 ret
= search_dir(search_root
, &location
, dir
);
664 btrfs_free_path(path
);
673 printf("Done searching %s\n", dir
);
674 btrfs_free_path(path
);
680 fprintf(stderr
, "Usage: restore [-svio] [-t disk offset] <device> "
684 static struct btrfs_root
*open_fs(const char *dev
, u64 root_location
, int super_mirror
)
686 struct btrfs_root
*root
;
690 for (i
= super_mirror
; i
< BTRFS_SUPER_MIRROR_MAX
; i
++) {
691 bytenr
= btrfs_sb_offset(i
);
692 root
= open_ctree_recovery(dev
, bytenr
, root_location
);
695 fprintf(stderr
, "Could not open root, trying backup super\n");
701 static int find_first_dir(struct btrfs_root
*root
, u64
*objectid
)
703 struct btrfs_path
*path
;
704 struct btrfs_key found_key
;
705 struct btrfs_key key
;
710 key
.type
= BTRFS_DIR_INDEX_KEY
;
713 path
= btrfs_alloc_path();
715 fprintf(stderr
, "Ran out of memory\n");
719 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
721 fprintf(stderr
, "Error searching %d\n", ret
);
725 if (!path
->nodes
[0]) {
726 fprintf(stderr
, "No leaf!\n");
730 for (i
= path
->slots
[0];
731 i
< btrfs_header_nritems(path
->nodes
[0]); i
++) {
732 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, i
);
733 if (found_key
.type
!= key
.type
)
736 printf("Using objectid %Lu for first dir\n",
738 *objectid
= found_key
.objectid
;
743 ret
= next_leaf(root
, path
);
745 fprintf(stderr
, "Error getting next leaf %d\n",
748 } else if (ret
> 0) {
749 fprintf(stderr
, "No more leaves\n");
752 } while (!path
->nodes
[0]);
755 printf("Couldn't find a dir index item\n");
757 btrfs_free_path(path
);
761 int main(int argc
, char **argv
)
763 struct btrfs_root
*root
;
764 struct btrfs_key key
;
766 u64 tree_location
= 0;
771 int super_mirror
= 0;
774 while ((opt
= getopt(argc
, argv
, "sviot:u:df:")) != -1) {
790 tree_location
= (u64
)strtoll(optarg
, NULL
, 10);
792 fprintf(stderr
, "Tree location not valid\n");
798 fs_location
= (u64
)strtoll(optarg
, NULL
, 10);
800 fprintf(stderr
, "Fs location not valid\n");
806 super_mirror
= (int)strtol(optarg
, NULL
, 10);
808 super_mirror
>= BTRFS_SUPER_MIRROR_MAX
) {
809 fprintf(stderr
, "Super mirror not "
823 if (optind
+ 1 >= argc
) {
828 if ((ret
= check_mounted(argv
[optind
])) < 0) {
829 fprintf(stderr
, "Could not check mount status: %s\n",
833 fprintf(stderr
, "%s is currently mounted. Aborting.\n", argv
[optind
]);
837 root
= open_fs(argv
[optind
], tree_location
, super_mirror
);
841 if (fs_location
!= 0) {
842 free_extent_buffer(root
->node
);
843 root
->node
= read_tree_block(root
, fs_location
, 4096, 0);
845 fprintf(stderr
, "Failed to read fs location\n");
850 printf("Root objectid is %Lu\n", root
->objectid
);
852 memset(path_name
, 0, 4096);
854 strncpy(dir_name
, argv
[optind
+ 1], sizeof dir_name
);
855 dir_name
[sizeof dir_name
- 1] = 0;
857 /* Strip the trailing / on the dir name */
858 len
= strlen(dir_name
);
859 while (len
&& dir_name
[--len
] == '/') {
860 dir_name
[len
] = '\0';
864 ret
= find_first_dir(root
, &key
.objectid
);
868 key
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
871 ret
= search_dir(root
->fs_info
->fs_root
, &key
, dir_name
);