From a780325614c0d89c9c0ea6779ada5af512b6e319 Mon Sep 17 00:00:00 2001 From: David Marcin Date: Tue, 22 Nov 2011 10:09:35 -0800 Subject: [PATCH 27/35] btrfs-progs: Use oldest super for btrfs-select-super. Add required confirmation to btrfs-select-super. Signed-off-by: David Marcin --- btrfs-select-super.c | 38 ++++++++++++++++++++++++++++++-------- disk-io.c | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/btrfs-select-super.c b/btrfs-select-super.c index 51eb9c9..4d27f1b 100644 --- a/btrfs-select-super.c +++ b/btrfs-select-super.c @@ -34,7 +34,9 @@ static void print_usage(void) { - fprintf(stderr, "usage: btrfs-select-super -s number dev\n"); + fprintf(stderr, "usage: btrfs-select-super [-c] [-e] -s number dev\n"); + fprintf(stderr, " -c Commit changes to disk [IRREVERSIBLE]\n"); + fprintf(stderr, " -e Use the earliest super found, may help recover transid verify problems\n"); fprintf(stderr, "%s\n", BTRFS_BUILD_VERSION); exit(1); } @@ -45,10 +47,13 @@ int main(int ac, char **av) int ret; int num; u64 bytenr = 0; + int commit = 0; + int use_lowest_bdev = 0; + int fp; while(1) { int c; - c = getopt(ac, av, "s:"); + c = getopt(ac, av, "s:ce"); if (c < 0) break; switch(c) { @@ -58,6 +63,12 @@ int main(int ac, char **av) printf("using SB copy %d, bytenr %llu\n", num, (unsigned long long)bytenr); break; + case 'c': + commit = 1; + break; + case 'e': + use_earliest_bdev = 1; + break; default: print_usage(); } @@ -74,22 +85,33 @@ int main(int ac, char **av) radix_tree_init(); - if((ret = check_mounted(av[optind])) < 0) { + if ((ret = check_mounted(av[optind])) < 0) { fprintf(stderr, "Could not check mount status: %s\n", strerror(-ret)); return ret; - } else if(ret) { + } else if (ret) { fprintf(stderr, "%s is currently mounted. Aborting.\n", av[optind]); return -EBUSY; } - root = open_ctree(av[optind], bytenr, 1); + fp = open(av[optind], O_CREAT|O_RDRW, 0600); + if (fp < 0) { + fprintf(stderr, "Could not open %s\n", av[optind]); + return 1; + } + root = open_ctree_fd(fp, av[optind], bytenr, 1, use_earliest_bdev); if (root == NULL) return 1; - /* make the super writing code think we've read the first super */ - root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET; - ret = write_all_supers(root); + fprintf(stderr, "Found superblock with generation %llu.\n", root->fs_info->super_copy.generation); + + if (commit) { + fprintf(stderr, "Committing...\n"); + + /* make the super writing code think we've read the first super */ + root->fs_info->super_bytenr = BTRFS_SUPER_INFO_OFFSET; + ret = write_all_supers(root); + } /* we don't close the ctree or anything, because we don't want a real * transaction commit. We just want the super copy we pulled off the diff --git a/disk-io.c b/disk-io.c index a161f15..9585057 100644 --- a/disk-io.c +++ b/disk-io.c @@ -871,7 +871,7 @@ struct btrfs_root *open_ctree_recovery(const char *filename, u64 sb_bytenr, fprintf (stderr, "Could not open %s\n", filename); return NULL; } - root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0); + root = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr, 0, 0); close(fp); return root; -- 1.7.6.233.gd79bc