On Tue, Nov 8, 2011 at 3:20 PM, Chris Mason <chris.mason@xxxxxxxxxx> wrote:
> On Tue, Nov 08, 2011 at 03:08:41PM -0200, Gustavo Sverzut Barbieri wrote:
>> On Tue, Nov 1, 2011 at 9:20 PM, Gustavo Sverzut Barbieri
>> <barbieri@xxxxxxxxx> wrote:
>> > On Tue, Nov 1, 2011 at 7:57 PM, Alexandre Oliva <oliva@xxxxxxxxxxxxxxxxx> wrote:
>> >> Hi, Gustavo,
>> >>
>> >> On Nov 1, 2011, Gustavo Sverzut Barbieri <barbieri@xxxxxxxxx> wrote:
>> >>
>> >>> btrfs csum failed ino 2957021 extent 85041815552 csum 667310679
>> >>> wanted 0 mirror 0
>> >>
>> >>> Is there any way to recover it? :-S
>> >>
>> >> Did you try mounting without data checksums?
>> >
>> > Just tried to mount with -o nodatasum, no luck. Is that enough?
>>
>> Ideas? Should I give up and consider data lost? :-(
>
> We actually check the crcs even when mounted with nodatasum. Can you
> give the restore tool a shot from my current btrfs-progs git repo? If
> it can read it we can find a way to get the files off.
Hi Chris,
Fortunately it worked and I've restored, it misses symbolic links and
executable permissions (or I did a mistake somewhere, like mounting)
but overall it's all fine.
The attached patch was helpful to let me ignore stuff like development
files and caches. Speeds up the recovery :-)
Thanks!
--
Gustavo Sverzut Barbieri
--------------------------------------
Mobile: +55 (19) 9225-2202
Contact: http://www.gustavobarbieri.com.br/contact
From dc57b73b08fefb21099cc6b171683daaffa04501 Mon Sep 17 00:00:00 2001
From: Gustavo Sverzut Barbieri <barbieri@xxxxxxxxxxxxxx>
Date: Mon, 8 Jan 2001 00:37:39 -0200
Subject: [PATCH] restore: allow ignoring file name patterns and paths.
Introduce two new command line switches that can be specified multiple
times:
-e path-pattern
-E file-name-pattern
They are processed with fnmatch(), the first (-e) using FNM_PATHNAME
flag on the whole path string, the second uses no flag and is applied
only over the file or directory name.
Example:
restore -v \
-e '*/.cache' -e '*/.thumbnails' \
-e '*/Desktop/Pictures' \
-E '*~' \
/dev/sdb1 /tmp/home-restore
will restore everything but files under ~/.cache, ~/.thumbnails and
~/Desktop/Pictures for every user (assume it's the mountpoint of
/home), also ignoring every backup file (*~).
---
restore.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/restore.c b/restore.c
index 250c9d3..bdb0c7f 100644
--- a/restore.c
+++ b/restore.c
@@ -25,6 +25,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <zlib.h>
+#include <fnmatch.h>
#include "kerncompat.h"
#include "ctree.h"
#include "disk-io.h"
@@ -40,6 +41,9 @@ static int get_snaps = 0;
static int verbose = 0;
static int ignore_errors = 0;
static int overwrite = 0;
+static char **exclude_paths = NULL;
+static char **exclude_patterns = NULL;
+static int dir_name_len = 0;
static int decompress(char *inbuf, char *outbuf, u64 compress_len,
u64 decompress_len)
@@ -436,6 +440,27 @@ set_size:
return 0;
}
+static int is_excluded(const char *path, const char *name)
+{
+ char **itr;
+ if (exclude_paths) {
+ path += dir_name_len;
+ for (itr = exclude_paths; *itr != NULL; itr++) {
+ if (fnmatch(*itr, path, FNM_PATHNAME) == 0) {
+ return 1;
+ }
+ }
+ }
+ if (exclude_patterns) {
+ for (itr = exclude_patterns; *itr != NULL; itr++) {
+ if (fnmatch(*itr, path, 0) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
const char *dir)
{
@@ -568,6 +593,11 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
}
ret = 0;
}
+ if (is_excluded(path_name, filename)) {
+ if (verbose)
+ printf("Ignored %s\n", path_name);
+ goto next;
+ }
if (verbose)
printf("Restoring %s\n", path_name);
fd = open(path_name, O_CREAT|O_WRONLY, 0644);
@@ -636,6 +666,11 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key,
location.objectid = BTRFS_FIRST_FREE_OBJECTID;
}
+ if (is_excluded(path_name, filename)) {
+ if (verbose)
+ printf("Ignored %s\n", path_name);
+ goto next;
+ }
if (verbose)
printf("Restoring %s\n", path_name);
@@ -672,7 +707,7 @@ next:
static void usage()
{
- fprintf(stderr, "Usage: restore [-svio] [-t disk offset] <device> "
+ fprintf(stderr, "Usage: restore [-svio] [-e exclude-paths] [-E exclude-name-patterns] [-t disk offset] <device> "
"<directory>\n");
}
@@ -765,8 +800,15 @@ int main(int argc, char **argv)
int opt;
int super_mirror = 0;
int find_dir = 0;
+ int exclude_paths_idx = 0;
+ int exclude_patterns_idx = 0;
- while ((opt = getopt(argc, argv, "sviot:u:df:")) != -1) {
+ if (argc > 1) {
+ exclude_paths = calloc(argc - 1, sizeof(char *));
+ exclude_patterns = calloc(argc - 1, sizeof(char *));
+ }
+
+ while ((opt = getopt(argc, argv, "sviot:u:df:e:E:")) != -1) {
switch (opt) {
case 's':
get_snaps = 1;
@@ -806,6 +848,14 @@ int main(int argc, char **argv)
exit(1);
}
break;
+ case 'e':
+ exclude_paths[exclude_paths_idx] = strdup(optarg);
+ exclude_paths_idx++;
+ break;
+ case 'E':
+ exclude_patterns[exclude_patterns_idx] = strdup(optarg);
+ exclude_patterns_idx++;
+ break;
case 'd':
find_dir = 1;
break;
@@ -855,6 +905,7 @@ int main(int argc, char **argv)
break;
dir_name[len - 1] = '\0';
}
+ dir_name_len = strlen(dir_name);
if (find_dir) {
ret = find_first_dir(root, &key.objectid);
--
1.7.7.1