Upstream-Status: Inappropriate [Backport] From 238f88bb6c4b9ebad727c6bffb57f542e7e412c1 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Sun, 19 Dec 2010 16:22:31 -0500 Subject: [PATCH 4/5] Allow partial FS opens for btrfsck scanning Signed-off-by: Chris Mason --- btrfsck.c | 10 ++++++++-- convert.c | 20 ++++++++++++++------ disk-io.c | 57 +++++++++++++++++++++++++++++++++++++++++---------------- disk-io.h | 5 +++-- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/btrfsck.c b/btrfsck.c index 63e44d1..f760706 100644 --- a/btrfsck.c +++ b/btrfsck.c @@ -2820,6 +2820,7 @@ int main(int ac, char **av) { struct cache_tree root_cache; struct btrfs_root *root; + struct btrfs_fs_info *info; u64 bytenr = 0; int ret; int num; @@ -2856,11 +2857,16 @@ int main(int ac, char **av) return -EBUSY; } - root = open_ctree(av[optind], bytenr, 0); + info = open_fs_info(av[optind], bytenr, 0, 1); - if (root == NULL) + if (info == NULL) return 1; + root = info->fs_root; + if (!root) { + fprintf(stderr, "failed to read the filesystem\n"); + exit(1); + } ret = check_extents(root); if (ret) goto out; diff --git a/convert.c b/convert.c index fbcf4a3..72e3cdc 100644 --- a/convert.c +++ b/convert.c @@ -2342,6 +2342,7 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr) ext2_filsys ext2_fs; struct btrfs_root *root; struct btrfs_root *ext2_root; + struct btrfs_fs_info *fs_info; ret = open_ext2fs(devname, &ext2_fs); if (ret) { @@ -2386,11 +2387,12 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr) fprintf(stderr, "unable to update system chunk\n"); goto fail; } - root = open_ctree_fd(fd, devname, super_bytenr, O_RDWR); - if (!root) { + fs_info = open_ctree_fd(fd, devname, super_bytenr, O_RDWR, 0); + if (!fs_info) { fprintf(stderr, "unable to open ctree\n"); goto fail; } + root = fs_info->fs_root; ret = cache_free_extents(root, ext2_fs); if (ret) { fprintf(stderr, "error during cache_free_extents %d\n", ret); @@ -2447,11 +2449,13 @@ int do_convert(const char *devname, int datacsum, int packing, int noxattr) goto fail; } - root = open_ctree_fd(fd, devname, 0, O_RDWR); - if (!root) { + fs_info = open_ctree_fd(fd, devname, 0, O_RDWR, 0); + if (!fs_info) { fprintf(stderr, "unable to open ctree\n"); goto fail; } + root = fs_info->fs_root; + /* move chunk tree into system chunk. */ ret = fixup_chunk_mapping(root); if (ret) { @@ -2525,6 +2529,7 @@ int do_rollback(const char *devname, int force) struct btrfs_key key; struct btrfs_path path; struct extent_io_tree io_tree; + struct btrfs_fs_info *fs_info; char *buf; char *name; u64 bytenr; @@ -2546,11 +2551,14 @@ int do_rollback(const char *devname, int force) fprintf(stderr, "unable to open %s\n", devname); goto fail; } - root = open_ctree_fd(fd, devname, 0, O_RDWR); - if (!root) { + + fs_info = open_ctree_fd(fd, devname, 0, O_RDWR, 0); + if (!fs_info) { fprintf(stderr, "unable to open ctree\n"); goto fail; } + root = fs_info->fs_root; + ret = may_rollback(root); if (ret < 0) { fprintf(stderr, "unable to do rollback\n"); diff --git a/disk-io.c b/disk-io.c index f4368f3..dc100b0 100644 --- a/disk-io.c +++ b/disk-io.c @@ -441,7 +441,8 @@ static int find_and_setup_log_root(struct btrfs_root *tree_root, btrfs_super_generation(disk_super) + 1); fs_info->log_root_tree = log_root; - BUG_ON(!log_root->node); + if (!log_root->node) + return -EIO; return 0; } @@ -571,10 +572,11 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, return root; } -struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes) +struct btrfs_fs_info *open_fs_info(const char *filename, u64 sb_bytenr, + int writes, int partial) { int fp; - struct btrfs_root *root; + struct btrfs_fs_info *fs_info; int flags = O_CREAT | O_RDWR; if (!writes) @@ -585,14 +587,25 @@ struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes) fprintf (stderr, "Could not open %s\n", filename); return NULL; } - root = open_ctree_fd(fp, filename, sb_bytenr, writes); + fs_info = open_ctree_fd(fp, filename, sb_bytenr, writes, partial); + close(fp); + return fs_info; +} - return root; + +struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes) +{ + struct btrfs_fs_info *fs_info; + + fs_info = open_fs_info(filename, sb_bytenr, writes, 0); + if (fs_info) + return fs_info->fs_root; + return NULL; } -struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, - int writes) +struct btrfs_fs_info *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, + int writes, int partial) { u32 sectorsize; u32 nodesize; @@ -727,7 +740,8 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, if (!(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_METADUMP)) { ret = btrfs_read_chunk_tree(chunk_root); - BUG_ON(ret); + if (ret) + goto fail; } blocksize = btrfs_level_size(tree_root, @@ -737,25 +751,32 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, tree_root->node = read_tree_block(tree_root, btrfs_super_root(disk_super), blocksize, generation); - BUG_ON(!tree_root->node); + if (!tree_root->node) + goto fail; + ret = find_and_setup_root(tree_root, fs_info, BTRFS_EXTENT_TREE_OBJECTID, extent_root); - BUG_ON(ret); + if (ret) + goto fail; + extent_root->track_dirty = 1; ret = find_and_setup_root(tree_root, fs_info, BTRFS_DEV_TREE_OBJECTID, dev_root); - BUG_ON(ret); + if (ret) + goto fail; + dev_root->track_dirty = 1; ret = find_and_setup_root(tree_root, fs_info, BTRFS_CSUM_TREE_OBJECTID, csum_root); - BUG_ON(ret); + if (ret) + goto fail; csum_root->track_dirty = 1; - BUG_ON(ret); - - find_and_setup_log_root(tree_root, fs_info, disk_super); + ret = find_and_setup_log_root(tree_root, fs_info, disk_super); + if (ret) + goto fail; fs_info->generation = generation + 1; btrfs_read_block_groups(fs_info->tree_root); @@ -769,7 +790,11 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, fs_info->metadata_alloc_profile = (u64)-1; fs_info->system_alloc_profile = fs_info->metadata_alloc_profile; - return fs_info->fs_root; + return fs_info; +fail: + if (partial) + return fs_info; + return NULL; } int btrfs_read_dev_super(int fd, struct btrfs_super_block *sb, u64 sb_bytenr) diff --git a/disk-io.h b/disk-io.h index 7ebec24..03c5eee 100644 --- a/disk-io.h +++ b/disk-io.h @@ -44,8 +44,9 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root, int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf); struct btrfs_root *open_ctree(const char *filename, u64 sb_bytenr, int writes); -struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, - int writes); +struct btrfs_fs_info *open_fs_info(const char *filename, u64 sb_bytenr, int writes, int partial); +struct btrfs_fs_info *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, + int writes, int partial); int close_ctree(struct btrfs_root *root); int write_all_supers(struct btrfs_root *root); int write_ctree_super(struct btrfs_trans_handle *trans, -- 1.7.2.3