summaryrefslogtreecommitdiff
path: root/disk-io.c
diff options
context:
space:
mode:
authorLu Fengqi <lufq.fnst@cn.fujitsu.com>2016-03-07 12:57:41 +0800
committerDavid Sterba <dsterba@suse.com>2016-03-14 13:42:47 +0100
commit05640939ea24c609c7c2badc76ebba9ec6a4896d (patch)
tree1ee641f486db5a5767aa52d8f2603eae73451b10 /disk-io.c
parentda3ae9c69ab4e557e625cabe8894e442def60b62 (diff)
btrfs-progs: Add new option for specify chunk root bytenr
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>
Diffstat (limited to 'disk-io.c')
-rw-r--r--disk-io.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/disk-io.c b/disk-io.c
index e520d80d..88015b72 100644
--- 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)