From 7985fe64e0e290d6107bc4218920238928300010 Mon Sep 17 00:00:00 2001 From: Wang Shilong Date: Sat, 21 Sep 2013 16:34:18 +0800 Subject: Btrfs-progs: add super-recover to recover bad supers Until now if one of device's first superblock is corrupt,btrfs will fail to mount. Luckily, btrfs have at least two superblocks for every disk. In theory, if silent corrupting happens when we are writting superblocks into disk, we must hold at least one good superblock. One side effect is that user must gurantee that the disk must be a btrfs disk. Otherwise, this tool may destroy other fs.(This is also reason why btrfs only use first superblock in every disk to mount) This little program will try to correct bad superblocks from good superblocks with max generation. There will be five kinds of return values: 0: all supers are valid, no need to recover 1: usage or syntax error 2: recover all bad superblocks successfully 3: fail to recover bad superblocks 4: abort to recover bad superblocks Signed-off-by: Wang Shilong Signed-off-by: David Sterba Signed-off-by: Chris Mason --- cmds-rescue.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'cmds-rescue.c') diff --git a/cmds-rescue.c b/cmds-rescue.c index cfbc198a..e18eb989 100644 --- a/cmds-rescue.c +++ b/cmds-rescue.c @@ -28,6 +28,7 @@ static const char * const rescue_cmd_group_usage[] = { }; int btrfs_recover_chunk_tree(char *path, int verbose, int yes); +int btrfs_recover_superblocks(char *path, int verbose, int yes); const char * const cmd_chunk_recover_usage[] = { "btrfs rescue chunk-recover [options] ", @@ -39,6 +40,15 @@ const char * const cmd_chunk_recover_usage[] = { NULL }; +const char * const cmd_super_recover_usage[] = { + "btrfs rescue super-recover [options] ", + "Recover bad superblocks from good copies", + "", + "-y Assume an answer of `yes' to all questions", + "-v Verbose mode", + NULL +}; + int cmd_chunk_recover(int argc, char *argv[]) { int ret = 0; @@ -87,9 +97,54 @@ int cmd_chunk_recover(int argc, char *argv[]) return ret; } +/* + * return codes: + * 0 : All superblocks are valid, no need to recover + * 1 : Usage or syntax error + * 2 : Recover all bad superblocks successfully + * 3 : Fail to Recover bad supeblocks + * 4 : Abort to recover bad superblocks + */ +int cmd_super_recover(int argc, char **argv) +{ + int ret; + int verbose = 0; + int yes = 0; + char *dname; + + while (1) { + int c = getopt(argc, argv, "vy"); + if (c < 0) + break; + switch (c) { + case 'v': + verbose = 1; + break; + case 'y': + yes = 1; + break; + default: + usage(cmd_super_recover_usage); + } + } + argc = argc - optind; + if (argc != 1) + usage(cmd_super_recover_usage); + + dname = argv[optind]; + ret = check_mounted(dname); + if (ret) { + fprintf(stderr, "the device is busy\n"); + return 1; + } + ret = btrfs_recover_superblocks(dname, verbose, yes); + return ret; +} + const struct cmd_group rescue_cmd_group = { rescue_cmd_group_usage, NULL, { { "chunk-recover", cmd_chunk_recover, cmd_chunk_recover_usage, NULL, 0}, + { "super-recover", cmd_super_recover, cmd_super_recover_usage, NULL, 0}, { 0, 0, 0, 0, 0 } } }; -- cgit v1.2.3