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
28 #include "kerncompat.h"
31 #include "print-tree.h"
32 #include "transaction.h"
38 static char path_name
[4096];
39 static int get_snaps
= 0;
40 static int verbose
= 0;
41 static int ignore_errors
= 0;
42 static int overwrite
= 0;
44 static int decompress(char *inbuf
, char *outbuf
, u64 compress_len
,
50 memset(&strm
, 0, sizeof(strm
));
51 ret
= inflateInit(&strm
);
53 fprintf(stderr
, "inflate init returnd %d\n", ret
);
57 strm
.avail_in
= compress_len
;
58 strm
.next_in
= (unsigned char *)inbuf
;
59 strm
.avail_out
= decompress_len
;
60 strm
.next_out
= (unsigned char *)outbuf
;
61 ret
= inflate(&strm
, Z_NO_FLUSH
);
62 if (ret
!= Z_STREAM_END
) {
63 (void)inflateEnd(&strm
);
64 fprintf(stderr
, "ret is %d\n", ret
);
68 (void)inflateEnd(&strm
);
72 int next_leaf(struct btrfs_root
*root
, struct btrfs_path
*path
)
76 struct extent_buffer
*c
;
77 struct extent_buffer
*next
= NULL
;
79 for (; level
< BTRFS_MAX_LEVEL
; level
++) {
80 if (path
->nodes
[level
])
84 if (level
== BTRFS_MAX_LEVEL
)
87 slot
= path
->slots
[level
] + 1;
89 while(level
< BTRFS_MAX_LEVEL
) {
90 if (!path
->nodes
[level
])
93 slot
= path
->slots
[level
] + 1;
94 c
= path
->nodes
[level
];
95 if (slot
>= btrfs_header_nritems(c
)) {
97 if (level
== BTRFS_MAX_LEVEL
)
103 free_extent_buffer(next
);
106 reada_for_search(root
, path
, level
, slot
, 0);
108 next
= read_node_slot(root
, c
, slot
);
111 path
->slots
[level
] = slot
;
114 c
= path
->nodes
[level
];
115 free_extent_buffer(c
);
116 path
->nodes
[level
] = next
;
117 path
->slots
[level
] = 0;
121 reada_for_search(root
, path
, level
, 0, 0);
122 next
= read_node_slot(root
, next
, 0);
127 static int copy_one_inline(int fd
, struct btrfs_path
*path
, u64 pos
)
129 struct extent_buffer
*leaf
= path
->nodes
[0];
130 struct btrfs_file_extent_item
*fi
;
140 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
141 struct btrfs_file_extent_item
);
142 ptr
= btrfs_file_extent_inline_start(fi
);
143 len
= btrfs_file_extent_inline_item_len(leaf
,
144 btrfs_item_nr(leaf
, path
->slots
[0]));
145 read_extent_buffer(leaf
, buf
, ptr
, len
);
147 compress
= btrfs_file_extent_compression(leaf
, fi
);
148 if (compress
== BTRFS_COMPRESS_NONE
) {
149 done
= pwrite(fd
, buf
, len
, pos
);
151 fprintf(stderr
, "Short inline write, wanted %d, did "
152 "%zd: %d\n", len
, done
, errno
);
158 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
159 outbuf
= malloc(ram_size
);
161 fprintf(stderr
, "No memory\n");
165 ret
= decompress(buf
, outbuf
, len
, ram_size
);
171 done
= pwrite(fd
, outbuf
, ram_size
, pos
);
174 fprintf(stderr
, "Short compressed inline write, wanted %d, "
175 "did %zd: %d\n", ram_size
, done
, errno
);
182 static int copy_one_extent(struct btrfs_root
*root
, int fd
,
183 struct extent_buffer
*leaf
,
184 struct btrfs_file_extent_item
*fi
, u64 pos
)
186 struct btrfs_multi_bio
*multi
= NULL
;
187 struct btrfs_device
*device
;
188 char *inbuf
, *outbuf
= NULL
;
189 ssize_t done
, total
= 0;
201 compress
= btrfs_file_extent_compression(leaf
, fi
);
202 bytenr
= btrfs_file_extent_disk_bytenr(leaf
, fi
);
203 disk_size
= btrfs_file_extent_disk_num_bytes(leaf
, fi
);
204 ram_size
= btrfs_file_extent_ram_bytes(leaf
, fi
);
205 size_left
= disk_size
;
207 /* we found a hole */
211 inbuf
= malloc(disk_size
);
213 fprintf(stderr
, "No memory\n");
217 if (compress
!= BTRFS_COMPRESS_NONE
) {
218 outbuf
= malloc(ram_size
);
220 fprintf(stderr
, "No memory\n");
227 ret
= btrfs_map_block(&root
->fs_info
->mapping_tree
, READ
,
228 bytenr
, &length
, &multi
, 0);
232 fprintf(stderr
, "Error mapping block %d\n", ret
);
235 device
= multi
->stripes
[0].dev
;
238 dev_bytenr
= multi
->stripes
[0].physical
;
241 if (size_left
< length
)
245 done
= pread(dev_fd
, inbuf
+count
, length
, dev_bytenr
);
249 fprintf(stderr
, "Short read %d\n", errno
);
259 if (compress
== BTRFS_COMPRESS_NONE
) {
260 while (total
< ram_size
) {
261 done
= pwrite(fd
, inbuf
+total
, ram_size
-total
,
265 fprintf(stderr
, "Error writing: %d %s\n", errno
, strerror(errno
));
274 ret
= decompress(inbuf
, outbuf
, disk_size
, ram_size
);
281 while (total
< ram_size
) {
282 done
= pwrite(fd
, outbuf
+total
, ram_size
-total
, pos
+total
);
285 fprintf(stderr
, "Error writing: %d %s\n", errno
, strerror(errno
));
295 static int ask_to_continue(const char *file
)
300 printf("We seem to be looping a lot on %s, do you want to keep going "
301 "on ? (y/N): ", file
);
303 ret
= fgets(buf
, 2, stdin
);
304 if (*ret
== '\n' || tolower(*ret
) == 'n')
306 if (tolower(*ret
) != 'y') {
307 printf("Please enter either 'y' or 'n': ");
315 static int copy_file(struct btrfs_root
*root
, int fd
, struct btrfs_key
*key
,
318 struct extent_buffer
*leaf
;
319 struct btrfs_path
*path
;
320 struct btrfs_file_extent_item
*fi
;
321 struct btrfs_inode_item
*inode_item
;
322 struct btrfs_key found_key
;
329 path
= btrfs_alloc_path();
331 fprintf(stderr
, "Ran out of memory\n");
334 path
->skip_locking
= 1;
336 ret
= btrfs_lookup_inode(NULL
, root
, path
, key
, 0);
338 inode_item
= btrfs_item_ptr(path
->nodes
[0], path
->slots
[0],
339 struct btrfs_inode_item
);
340 found_size
= btrfs_inode_size(path
->nodes
[0], inode_item
);
342 btrfs_release_path(root
, path
);
345 key
->type
= BTRFS_EXTENT_DATA_KEY
;
347 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
349 fprintf(stderr
, "Error searching %d\n", ret
);
350 btrfs_free_path(path
);
354 leaf
= path
->nodes
[0];
356 ret
= next_leaf(root
, path
);
358 fprintf(stderr
, "Error getting next leaf %d\n",
360 btrfs_free_path(path
);
362 } else if (ret
> 0) {
363 /* No more leaves to search */
364 btrfs_free_path(path
);
367 leaf
= path
->nodes
[0];
371 if (loops
++ >= 1024) {
372 ret
= ask_to_continue(file
);
377 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
379 ret
= next_leaf(root
, path
);
381 fprintf(stderr
, "Error searching %d\n", ret
);
382 btrfs_free_path(path
);
385 /* No more leaves to search */
386 btrfs_free_path(path
);
390 leaf
= path
->nodes
[0];
394 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
395 if (found_key
.objectid
!= key
->objectid
)
397 if (found_key
.type
!= key
->type
)
399 fi
= btrfs_item_ptr(leaf
, path
->slots
[0],
400 struct btrfs_file_extent_item
);
401 extent_type
= btrfs_file_extent_type(leaf
, fi
);
402 compression
= btrfs_file_extent_compression(leaf
, fi
);
403 if (compression
>= BTRFS_COMPRESS_LAST
) {
404 fprintf(stderr
, "Don't support compression yet %d\n",
406 btrfs_free_path(path
);
410 if (extent_type
== BTRFS_FILE_EXTENT_PREALLOC
)
412 if (extent_type
== BTRFS_FILE_EXTENT_INLINE
) {
413 ret
= copy_one_inline(fd
, path
, found_key
.offset
);
415 btrfs_free_path(path
);
418 } else if (extent_type
== BTRFS_FILE_EXTENT_REG
) {
419 ret
= copy_one_extent(root
, fd
, leaf
, fi
,
422 btrfs_free_path(path
);
426 printf("Weird extent type %d\n", extent_type
);
432 btrfs_free_path(path
);
435 ftruncate(fd
, (loff_t
)found_size
);
439 static int search_dir(struct btrfs_root
*root
, struct btrfs_key
*key
,
442 struct btrfs_path
*path
;
443 struct extent_buffer
*leaf
;
444 struct btrfs_dir_item
*dir_item
;
445 struct btrfs_key found_key
, location
;
446 char filename
[BTRFS_NAME_LEN
+ 1];
447 unsigned long name_ptr
;
454 path
= btrfs_alloc_path();
456 fprintf(stderr
, "Ran out of memory\n");
459 path
->skip_locking
= 1;
462 key
->type
= BTRFS_DIR_INDEX_KEY
;
464 ret
= btrfs_search_slot(NULL
, root
, key
, path
, 0, 0);
466 fprintf(stderr
, "Error searching %d\n", ret
);
467 btrfs_free_path(path
);
471 leaf
= path
->nodes
[0];
474 printf("No leaf after search, looking for the next "
476 ret
= next_leaf(root
, path
);
478 fprintf(stderr
, "Error getting next leaf %d\n",
480 btrfs_free_path(path
);
482 } else if (ret
> 0) {
483 /* No more leaves to search */
485 printf("Reached the end of the tree looking "
486 "for the directory\n");
487 btrfs_free_path(path
);
490 leaf
= path
->nodes
[0];
494 if (loops
++ >= 1024) {
495 printf("We have looped trying to restore files in %s "
496 "too many times to be making progress, "
501 if (path
->slots
[0] >= btrfs_header_nritems(leaf
)) {
503 ret
= next_leaf(root
, path
);
505 fprintf(stderr
, "Error searching %d\n",
507 btrfs_free_path(path
);
509 } else if (ret
> 0) {
510 /* No more leaves to search */
512 printf("Reached the end of "
513 "the tree searching the"
515 btrfs_free_path(path
);
518 leaf
= path
->nodes
[0];
522 btrfs_item_key_to_cpu(leaf
, &found_key
, path
->slots
[0]);
523 if (found_key
.objectid
!= key
->objectid
) {
525 printf("Found objectid=%Lu, key=%Lu\n",
526 found_key
.objectid
, key
->objectid
);
529 if (found_key
.type
!= key
->type
) {
531 printf("Found type=%u, want=%u\n",
532 found_key
.type
, key
->type
);
535 dir_item
= btrfs_item_ptr(leaf
, path
->slots
[0],
536 struct btrfs_dir_item
);
537 name_ptr
= (unsigned long)(dir_item
+ 1);
538 name_len
= btrfs_dir_name_len(leaf
, dir_item
);
539 read_extent_buffer(leaf
, filename
, name_ptr
, name_len
);
540 filename
[name_len
] = '\0';
541 type
= btrfs_dir_type(leaf
, dir_item
);
542 btrfs_dir_item_key_to_cpu(leaf
, dir_item
, &location
);
544 snprintf(path_name
, 4096, "%s/%s", dir
, filename
);
548 * At this point we're only going to restore directories and
549 * files, no symlinks or anything else.
551 if (type
== BTRFS_FT_REG_FILE
) {
556 ret
= stat(path_name
, &st
);
559 if (verbose
|| !warn
)
560 printf("Skipping existing file"
564 printf("If you wish to overwrite use "
565 "the -o option to overwrite\n");
572 printf("Restoring %s\n", path_name
);
573 fd
= open(path_name
, O_CREAT
|O_WRONLY
, 0644);
575 fprintf(stderr
, "Error creating %s: %d\n",
579 btrfs_free_path(path
);
583 ret
= copy_file(root
, fd
, &location
, path_name
);
588 btrfs_free_path(path
);
591 } else if (type
== BTRFS_FT_DIR
) {
592 struct btrfs_root
*search_root
= root
;
593 char *dir
= strdup(path_name
);
596 fprintf(stderr
, "Ran out of memory\n");
597 btrfs_free_path(path
);
601 if (location
.type
== BTRFS_ROOT_ITEM_KEY
) {
603 * If we are a snapshot and this is the index
604 * object to ourselves just skip it.
606 if (location
.objectid
==
607 root
->root_key
.objectid
) {
612 search_root
= btrfs_read_fs_root(root
->fs_info
,
614 if (IS_ERR(search_root
)) {
616 fprintf(stderr
, "Error reading "
617 "subvolume %s: %lu\n",
619 PTR_ERR(search_root
));
622 return PTR_ERR(search_root
);
626 * A subvolume will have a key.offset of 0, a
627 * snapshot will have key.offset of a transid.
629 if (search_root
->root_key
.offset
!= 0 &&
632 printf("Skipping snapshot %s\n",
636 location
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
640 printf("Restoring %s\n", path_name
);
643 ret
= mkdir(path_name
, 0755);
644 if (ret
&& errno
!= EEXIST
) {
646 fprintf(stderr
, "Error mkdiring %s: %d\n",
650 btrfs_free_path(path
);
654 ret
= search_dir(search_root
, &location
, dir
);
659 btrfs_free_path(path
);
668 printf("Done searching %s\n", dir
);
669 btrfs_free_path(path
);
675 fprintf(stderr
, "Usage: restore [-svio] [-t disk offset] <device> "
679 static struct btrfs_root
*open_fs(const char *dev
, u64 root_location
, int super_mirror
)
681 struct btrfs_root
*root
;
685 for (i
= super_mirror
; i
< BTRFS_SUPER_MIRROR_MAX
; i
++) {
686 bytenr
= btrfs_sb_offset(i
);
687 root
= open_ctree_recovery(dev
, bytenr
, root_location
);
690 fprintf(stderr
, "Could not open root, trying backup super\n");
696 static int find_first_dir(struct btrfs_root
*root
, u64
*objectid
)
698 struct btrfs_path
*path
;
699 struct btrfs_key found_key
;
700 struct btrfs_key key
;
705 key
.type
= BTRFS_DIR_INDEX_KEY
;
708 path
= btrfs_alloc_path();
710 fprintf(stderr
, "Ran out of memory\n");
714 ret
= btrfs_search_slot(NULL
, root
, &key
, path
, 0, 0);
716 fprintf(stderr
, "Error searching %d\n", ret
);
720 if (!path
->nodes
[0]) {
721 fprintf(stderr
, "No leaf!\n");
725 for (i
= path
->slots
[0];
726 i
< btrfs_header_nritems(path
->nodes
[0]); i
++) {
727 btrfs_item_key_to_cpu(path
->nodes
[0], &found_key
, i
);
728 if (found_key
.type
!= key
.type
)
731 printf("Using objectid %Lu for first dir\n",
733 *objectid
= found_key
.objectid
;
738 ret
= next_leaf(root
, path
);
740 fprintf(stderr
, "Error getting next leaf %d\n",
743 } else if (ret
> 0) {
744 fprintf(stderr
, "No more leaves\n");
747 } while (!path
->nodes
[0]);
750 printf("Couldn't find a dir index item\n");
752 btrfs_free_path(path
);
756 int main(int argc
, char **argv
)
758 struct btrfs_root
*root
;
759 struct btrfs_key key
;
761 u64 tree_location
= 0;
766 int super_mirror
= 0;
769 while ((opt
= getopt(argc
, argv
, "sviot:u:df:")) != -1) {
785 tree_location
= (u64
)strtoll(optarg
, NULL
, 10);
787 fprintf(stderr
, "Tree location not valid\n");
793 fs_location
= (u64
)strtoll(optarg
, NULL
, 10);
795 fprintf(stderr
, "Fs location not valid\n");
801 super_mirror
= (int)strtol(optarg
, NULL
, 10);
803 super_mirror
>= BTRFS_SUPER_MIRROR_MAX
) {
804 fprintf(stderr
, "Super mirror not "
818 if (optind
+ 1 >= argc
) {
823 if ((ret
= check_mounted(argv
[optind
])) < 0) {
824 fprintf(stderr
, "Could not check mount status: %s\n",
828 fprintf(stderr
, "%s is currently mounted. Aborting.\n", argv
[optind
+ 1]);
832 root
= open_fs(argv
[optind
], tree_location
, super_mirror
);
836 if (fs_location
!= 0) {
837 free_extent_buffer(root
->node
);
838 root
->node
= read_tree_block(root
, fs_location
, 4096, 0);
840 fprintf(stderr
, "Failed to read fs location\n");
845 printf("Root objectid is %Lu\n", root
->objectid
);
847 memset(path_name
, 0, 4096);
849 strncpy(dir_name
, argv
[optind
+ 1], sizeof dir_name
);
850 dir_name
[sizeof dir_name
- 1] = 0;
852 /* Strip the trailing / on the dir name */
853 len
= strlen(dir_name
);
854 while (len
&& dir_name
[--len
] == '/') {
855 dir_name
[len
] = '\0';
859 ret
= find_first_dir(root
, &key
.objectid
);
863 key
.objectid
= BTRFS_FIRST_FREE_OBJECTID
;
866 ret
= search_dir(root
->fs_info
->fs_root
, &key
, dir_name
);