Re: corrupted btrfs after suspend2ram uncorrectable with scrub

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux