btrfs-progs: Add new option for specify chunk root bytenr
authorLu Fengqi <lufq.fnst@cn.fujitsu.com>
Mon, 7 Mar 2016 04:57:41 +0000 (12:57 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 14 Mar 2016 12:42:47 +0000 (13:42 +0100)
Add new btrfsck option, '--chunk-root', to specify chunk root bytenr.
And allow open_ctree_fs_info() function accept chunk_root_bytenr to
override the bytenr in superblock. This will be mainly used when chunk
tree corruption.

Signed-off-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
btrfs-find-root.c
btrfs-image.c
cmds-check.c
cmds-filesystem.c
cmds-inspect-dump-tree.c
cmds-restore.c
disk-io.c
disk-io.h

index e6ccc53..ed1540a 100644 (file)
@@ -190,7 +190,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       fs_info = open_ctree_fs_info(argv[optind], 0, 0,
+       fs_info = open_ctree_fs_info(argv[optind], 0, 0, 0,
                        OPEN_CTREE_CHUNK_ROOT_ONLY |
                        OPEN_CTREE_IGNORE_CHUNK_TREE_ERROR);
        if (!fs_info) {
index 33966fd..eba0e29 100644 (file)
@@ -2471,7 +2471,7 @@ static int restore_metadump(const char *input, FILE *out, int old_restore,
        /* NOTE: open with write mode */
        if (fixup_offset) {
                BUG_ON(!target);
-               info = open_ctree_fs_info(target, 0, 0,
+               info = open_ctree_fs_info(target, 0, 0, 0,
                                          OPEN_CTREE_WRITES |
                                          OPEN_CTREE_RESTORE |
                                          OPEN_CTREE_PARTIAL);
@@ -2817,7 +2817,7 @@ int main(int argc, char *argv[])
                u64 total_devs;
                int i;
 
-               info = open_ctree_fs_info(target, 0, 0,
+               info = open_ctree_fs_info(target, 0, 0, 0,
                                          OPEN_CTREE_PARTIAL |
                                          OPEN_CTREE_RESTORE);
                if (!info) {
index 8fb9771..0a48535 100644 (file)
@@ -9480,6 +9480,7 @@ const char * const cmd_check_usage[] = {
        "-E|--subvol-extents <subvolid>",
        "                            print subvolume extents and sharing state",
        "-r|--tree-root <bytenr>     use the given bytenr for the tree root",
+       "-c|--chunk-root <bytenr>    use the given bytenr for the chunk tree root",
        "-p|--progress               indicate progress",
        NULL
 };
@@ -9492,6 +9493,7 @@ int cmd_check(int argc, char **argv)
        u64 bytenr = 0;
        u64 subvolid = 0;
        u64 tree_root_bytenr = 0;
+       u64 chunk_root_bytenr = 0;
        char uuidbuf[BTRFS_UUID_UNPARSED_SIZE];
        int ret;
        u64 num;
@@ -9515,11 +9517,12 @@ int cmd_check(int argc, char **argv)
                        { "subvol-extents", required_argument, NULL, 'E' },
                        { "qgroup-report", no_argument, NULL, 'Q' },
                        { "tree-root", required_argument, NULL, 'r' },
+                       { "chunk-root", required_argument, NULL, 'c' },
                        { "progress", no_argument, NULL, 'p' },
                        { NULL, 0, NULL, 0}
                };
 
-               c = getopt_long(argc, argv, "as:br:p", long_options, NULL);
+               c = getopt_long(argc, argv, "as:br:pc:", long_options, NULL);
                if (c < 0)
                        break;
                switch(c) {
@@ -9548,6 +9551,9 @@ int cmd_check(int argc, char **argv)
                        case 'r':
                                tree_root_bytenr = arg_strtou64(optarg);
                                break;
+                       case 'c':
+                               chunk_root_bytenr = arg_strtou64(optarg);
+                               break;
                        case 'p':
                                ctx.progress_enabled = true;
                                break;
@@ -9611,7 +9617,7 @@ int cmd_check(int argc, char **argv)
                ctree_flags |= OPEN_CTREE_PARTIAL;
 
        info = open_ctree_fs_info(argv[optind], bytenr, tree_root_bytenr,
-                                 ctree_flags);
+                                 chunk_root_bytenr, ctree_flags);
        if (!info) {
                fprintf(stderr, "Couldn't open file system\n");
                ret = -EIO;
index ea66f8a..7e74e1b 100644 (file)
@@ -720,7 +720,7 @@ static int map_seed_devices(struct list_head *all_uuids)
                /*
                 * open_ctree_* detects seed/sprout mapping
                 */
-               fs_info = open_ctree_fs_info(device->name, 0, 0,
+               fs_info = open_ctree_fs_info(device->name, 0, 0, 0,
                                                OPEN_CTREE_PARTIAL);
                if (!fs_info)
                        continue;
index 39c5818..4614bbc 100644 (file)
@@ -194,7 +194,7 @@ int cmd_inspect_dump_tree(int argc, char **argv)
                goto out;
        }
 
-       info = open_ctree_fs_info(argv[optind], 0, 0, OPEN_CTREE_PARTIAL);
+       info = open_ctree_fs_info(argv[optind], 0, 0, 0, OPEN_CTREE_PARTIAL);
        if (!info) {
                error("unable to open %s", argv[optind]);
                goto out;
index 161fd91..0878b8e 100644 (file)
@@ -1262,7 +1262,7 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location,
 
        for (i = super_mirror; i < BTRFS_SUPER_MIRROR_MAX; i++) {
                bytenr = btrfs_sb_offset(i);
-               fs_info = open_ctree_fs_info(dev, bytenr, root_location,
+               fs_info = open_ctree_fs_info(dev, bytenr, root_location, 0,
                                             OPEN_CTREE_PARTIAL);
                if (fs_info)
                        break;
index e520d80..88015b7 100644 (file)
--- a/disk-io.c
+++ b/disk-io.c
@@ -1146,7 +1146,8 @@ int btrfs_scan_fs_devices(int fd, const char *path,
        return 0;
 }
 
-int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info)
+int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info,
+                                         u64 chunk_root_bytenr)
 {
        struct btrfs_super_block *sb = fs_info->super_copy;
        u32 sectorsize;
@@ -1173,8 +1174,20 @@ int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info)
                                     btrfs_super_chunk_root_level(sb));
        generation = btrfs_super_chunk_root_generation(sb);
 
+       if (chunk_root_bytenr && !IS_ALIGNED(chunk_root_bytenr,
+                                           btrfs_super_sectorsize(sb))) {
+               warning("chunk_root_bytenr %llu is unaligned to %u, ignore it",
+                       chunk_root_bytenr, btrfs_super_sectorsize(sb));
+               chunk_root_bytenr = 0;
+       }
+
+       if (!chunk_root_bytenr)
+               chunk_root_bytenr = btrfs_super_chunk_root(sb);
+       else
+               generation = 0;
+
        fs_info->chunk_root->node = read_tree_block(fs_info->chunk_root,
-                                                   btrfs_super_chunk_root(sb),
+                                                   chunk_root_bytenr,
                                                    blocksize, generation);
        if (!extent_buffer_uptodate(fs_info->chunk_root->node)) {
                if (fs_info->ignore_chunk_tree_error) {
@@ -1200,6 +1213,7 @@ int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info)
 static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
                                             u64 sb_bytenr,
                                             u64 root_tree_bytenr,
+                                            u64 chunk_root_bytenr,
                                             enum btrfs_open_ctree_flags flags)
 {
        struct btrfs_fs_info *fs_info;
@@ -1273,7 +1287,7 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
        if (ret)
                goto out_devices;
 
-       ret = btrfs_setup_chunk_tree_and_device_map(fs_info);
+       ret = btrfs_setup_chunk_tree_and_device_map(fs_info, chunk_root_bytenr);
        if (ret)
                goto out_chunk;
 
@@ -1305,6 +1319,7 @@ out:
 
 struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
                                         u64 sb_bytenr, u64 root_tree_bytenr,
+                                        u64 chunk_root_bytenr,
                                         enum btrfs_open_ctree_flags flags)
 {
        int fp;
@@ -1320,7 +1335,7 @@ struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
                return NULL;
        }
        info = __open_ctree_fd(fp, filename, sb_bytenr, root_tree_bytenr,
-                              flags);
+                              chunk_root_bytenr, flags);
        close(fp);
        return info;
 }
@@ -1332,7 +1347,7 @@ struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr,
 
        /* This flags may not return fs_info with any valid root */
        BUG_ON(flags & OPEN_CTREE_IGNORE_CHUNK_TREE_ERROR);
-       info = open_ctree_fs_info(filename, sb_bytenr, 0, flags);
+       info = open_ctree_fs_info(filename, sb_bytenr, 0, 0, flags);
        if (!info)
                return NULL;
        if (flags & __OPEN_CTREE_RETURN_CHUNK_ROOT)
@@ -1347,7 +1362,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
 
        /* This flags may not return fs_info with any valid root */
        BUG_ON(flags & OPEN_CTREE_IGNORE_CHUNK_TREE_ERROR);
-       info = __open_ctree_fd(fp, path, sb_bytenr, 0, flags);
+       info = __open_ctree_fd(fp, path, sb_bytenr, 0, 0, flags);
        if (!info)
                return NULL;
        if (flags & __OPEN_CTREE_RETURN_CHUNK_ROOT)
index 30ccb2b..b97b90b 100644 (file)
--- a/disk-io.h
+++ b/disk-io.h
@@ -109,7 +109,8 @@ void btrfs_cleanup_all_caches(struct btrfs_fs_info *fs_info);
 int btrfs_scan_fs_devices(int fd, const char *path,
                          struct btrfs_fs_devices **fs_devices, u64 sb_bytenr,
                          int super_recover, int skip_devices);
-int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info);
+int btrfs_setup_chunk_tree_and_device_map(struct btrfs_fs_info *fs_info,
+                         u64 chunk_root_bytenr);
 
 struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr,
                              enum btrfs_open_ctree_flags flags);
@@ -117,6 +118,7 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr,
                                 enum btrfs_open_ctree_flags flags);
 struct btrfs_fs_info *open_ctree_fs_info(const char *filename,
                                         u64 sb_bytenr, u64 root_tree_bytenr,
+                                        u64 chunk_root_bytenr,
                                         enum btrfs_open_ctree_flags flags);
 int close_ctree_fs_info(struct btrfs_fs_info *fs_info);
 static inline int close_ctree(struct btrfs_root *root)