2016-02-24 10:52:33 +00:00
|
|
|
/*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public
|
|
|
|
* License v2 as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public
|
|
|
|
* License along with this program; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 021110-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kerncompat.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
2016-03-15 15:31:58 +00:00
|
|
|
#include <getopt.h>
|
2016-02-24 10:52:33 +00:00
|
|
|
|
|
|
|
#include "ctree.h"
|
|
|
|
#include "disk-io.h"
|
2020-08-18 13:56:04 +00:00
|
|
|
#include "kernel-shared/print-tree.h"
|
2019-06-19 23:46:21 +00:00
|
|
|
#include "common/utils.h"
|
2019-06-19 23:46:21 +00:00
|
|
|
#include "cmds/commands.h"
|
2019-06-19 23:46:21 +00:00
|
|
|
#include "common/help.h"
|
2016-02-24 10:52:33 +00:00
|
|
|
|
|
|
|
static int load_and_dump_sb(char *filename, int fd, u64 sb_bytenr, int full,
|
|
|
|
int force)
|
|
|
|
{
|
|
|
|
u8 super_block_data[BTRFS_SUPER_INFO_SIZE];
|
|
|
|
struct btrfs_super_block *sb;
|
|
|
|
u64 ret;
|
|
|
|
|
|
|
|
sb = (struct btrfs_super_block *)super_block_data;
|
|
|
|
|
|
|
|
ret = pread64(fd, super_block_data, BTRFS_SUPER_INFO_SIZE, sb_bytenr);
|
|
|
|
if (ret != BTRFS_SUPER_INFO_SIZE) {
|
|
|
|
/* check if the disk if too short for further superblock */
|
|
|
|
if (ret == 0 && errno == 0)
|
|
|
|
return 0;
|
|
|
|
|
2016-03-02 14:47:19 +00:00
|
|
|
error("failed to read the superblock on %s at %llu",
|
|
|
|
filename, (unsigned long long)sb_bytenr);
|
2018-01-07 21:54:21 +00:00
|
|
|
error("error = '%m', errno = %d", errno);
|
2016-02-24 10:52:33 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
printf("superblock: bytenr=%llu, device=%s\n", sb_bytenr, filename);
|
|
|
|
printf("---------------------------------------------------------\n");
|
|
|
|
if (btrfs_super_magic(sb) != BTRFS_MAGIC && !force) {
|
2016-03-02 14:47:19 +00:00
|
|
|
error("bad magic on superblock on %s at %llu",
|
|
|
|
filename, (unsigned long long)sb_bytenr);
|
2016-02-24 10:52:33 +00:00
|
|
|
} else {
|
2020-05-27 10:28:06 +00:00
|
|
|
btrfs_print_superblock(sb, full);
|
2016-02-24 10:52:33 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-07 02:07:03 +00:00
|
|
|
static const char * const cmd_inspect_dump_super_usage[] = {
|
2016-02-24 10:52:33 +00:00
|
|
|
"btrfs inspect-internal dump-super [options] device [device...]",
|
2016-03-15 15:32:26 +00:00
|
|
|
"Dump superblock from a device in a textual form",
|
2019-06-21 13:36:04 +00:00
|
|
|
"",
|
2016-09-02 14:57:23 +00:00
|
|
|
"-f|--full print full superblock information, backup roots etc.",
|
|
|
|
"-a|--all print information about all superblocks",
|
|
|
|
"-s|--super <super> specify which copy to print out (values: 0, 1, 2)",
|
|
|
|
"-F|--force attempt to dump superblocks with bad magic",
|
|
|
|
"--bytenr <offset> specify alternate superblock offset",
|
|
|
|
"",
|
|
|
|
"Deprecated syntax:",
|
|
|
|
"-s <bytenr> specify alternate superblock offset, values other than 0, 1, 2",
|
|
|
|
" will be interpreted as --bytenr for backward compatibility,",
|
|
|
|
" option renamed for consistency with other tools (eg. check)",
|
|
|
|
"-i <super> specify which copy to print out (values: 0, 1, 2), now moved",
|
|
|
|
" to -s|--super",
|
2016-02-24 10:52:33 +00:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
2018-03-07 02:24:46 +00:00
|
|
|
static int cmd_inspect_dump_super(const struct cmd_struct *cmd,
|
|
|
|
int argc, char **argv)
|
2016-02-24 10:52:33 +00:00
|
|
|
{
|
|
|
|
int all = 0;
|
|
|
|
int full = 0;
|
|
|
|
int force = 0;
|
|
|
|
char *filename;
|
|
|
|
int fd = -1;
|
|
|
|
int i;
|
|
|
|
int ret = 0;
|
|
|
|
u64 arg;
|
|
|
|
u64 sb_bytenr = btrfs_sb_offset(0);
|
|
|
|
|
2016-03-15 15:31:58 +00:00
|
|
|
while (1) {
|
|
|
|
int c;
|
2017-08-24 05:25:29 +00:00
|
|
|
enum { GETOPT_VAL_BYTENR = 257 };
|
2016-03-15 15:31:58 +00:00
|
|
|
static const struct option long_options[] = {
|
2016-03-15 15:32:26 +00:00
|
|
|
{"all", no_argument, NULL, 'a'},
|
2017-08-24 05:25:29 +00:00
|
|
|
{"bytenr", required_argument, NULL, GETOPT_VAL_BYTENR },
|
2016-03-15 15:32:26 +00:00
|
|
|
{"full", no_argument, NULL, 'f'},
|
|
|
|
{"force", no_argument, NULL, 'F'},
|
2016-09-02 14:57:23 +00:00
|
|
|
{"super", required_argument, NULL, 's' },
|
2016-03-15 15:31:58 +00:00
|
|
|
{NULL, 0, NULL, 0}
|
|
|
|
};
|
|
|
|
|
|
|
|
c = getopt_long(argc, argv, "fFai:s:", long_options, NULL);
|
|
|
|
if (c < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
switch (c) {
|
2016-02-24 10:52:33 +00:00
|
|
|
case 'i':
|
2016-09-02 14:57:23 +00:00
|
|
|
warning(
|
|
|
|
"option -i is deprecated, please use -s or --super");
|
2016-02-24 10:52:33 +00:00
|
|
|
arg = arg_strtou64(optarg);
|
|
|
|
if (arg >= BTRFS_SUPER_MIRROR_MAX) {
|
2016-03-02 14:47:19 +00:00
|
|
|
error("super mirror too big: %llu >= %d",
|
|
|
|
arg, BTRFS_SUPER_MIRROR_MAX);
|
2016-09-02 14:57:23 +00:00
|
|
|
return 1;
|
2016-02-24 10:52:33 +00:00
|
|
|
}
|
|
|
|
sb_bytenr = btrfs_sb_offset(arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
all = 1;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
full = 1;
|
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
force = 1;
|
|
|
|
break;
|
|
|
|
case 's':
|
2016-09-02 14:57:23 +00:00
|
|
|
arg = arg_strtou64(optarg);
|
|
|
|
if (BTRFS_SUPER_MIRROR_MAX <= arg) {
|
|
|
|
warning(
|
|
|
|
"deprecated use of -s <bytenr> with %llu, assuming --bytenr",
|
|
|
|
(unsigned long long)arg);
|
|
|
|
sb_bytenr = arg;
|
|
|
|
} else {
|
|
|
|
sb_bytenr = btrfs_sb_offset(arg);
|
|
|
|
}
|
2016-02-24 10:52:33 +00:00
|
|
|
all = 0;
|
|
|
|
break;
|
2017-08-24 05:25:29 +00:00
|
|
|
case GETOPT_VAL_BYTENR:
|
|
|
|
arg = arg_strtou64(optarg);
|
|
|
|
sb_bytenr = arg;
|
|
|
|
all = 0;
|
|
|
|
break;
|
2016-02-24 10:52:33 +00:00
|
|
|
default:
|
2018-03-07 02:54:38 +00:00
|
|
|
usage_unknown_option(cmd, argv);
|
2016-02-24 10:52:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (check_argc_min(argc - optind, 1))
|
2019-03-04 13:49:15 +00:00
|
|
|
return 1;
|
2016-02-24 10:52:33 +00:00
|
|
|
|
|
|
|
for (i = optind; i < argc; i++) {
|
|
|
|
filename = argv[i];
|
2016-09-01 17:38:23 +00:00
|
|
|
fd = open(filename, O_RDONLY);
|
2016-02-24 10:52:33 +00:00
|
|
|
if (fd < 0) {
|
2018-01-07 21:54:21 +00:00
|
|
|
error("cannot open %s: %m", filename);
|
2016-02-24 10:52:33 +00:00
|
|
|
ret = 1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (all) {
|
|
|
|
int idx;
|
|
|
|
|
|
|
|
for (idx = 0; idx < BTRFS_SUPER_MIRROR_MAX; idx++) {
|
|
|
|
sb_bytenr = btrfs_sb_offset(idx);
|
|
|
|
if (load_and_dump_sb(filename, fd,
|
|
|
|
sb_bytenr, full, force)) {
|
|
|
|
close(fd);
|
|
|
|
ret = 1;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
load_and_dump_sb(filename, fd, sb_bytenr, full, force);
|
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
return ret;
|
|
|
|
}
|
2018-03-07 02:07:03 +00:00
|
|
|
DEFINE_SIMPLE_COMMAND(inspect_dump_super, "dump-super");
|