Btrfs-progs: check, ability to detect and fix outdated snapshot root items
[platform/upstream/btrfs-progs.git] / disk-io.c
index f71f5ca..77fc610 100644 (file)
--- a/disk-io.c
+++ b/disk-io.c
@@ -34,6 +34,7 @@
 #include "crc32c.h"
 #include "utils.h"
 #include "print-tree.h"
+#include "rbtree-utils.h"
 
 static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
 {
@@ -134,31 +135,26 @@ struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
                                   blocksize);
 }
 
-int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
-                        u64 parent_transid)
+void readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
+                         u64 parent_transid)
 {
-       int ret;
        struct extent_buffer *eb;
        u64 length;
        struct btrfs_multi_bio *multi = NULL;
        struct btrfs_device *device;
 
        eb = btrfs_find_tree_block(root, bytenr, blocksize);
-       if (eb && btrfs_buffer_uptodate(eb, parent_transid)) {
-               free_extent_buffer(eb);
-               return 0;
+       if (!(eb && btrfs_buffer_uptodate(eb, parent_transid)) &&
+           !btrfs_map_block(&root->fs_info->mapping_tree, READ,
+                            bytenr, &length, &multi, 0, NULL)) {
+               device = multi->stripes[0].dev;
+               device->total_ios++;
+               blocksize = min(blocksize, (u32)(64 * 1024));
+               readahead(device->fd, multi->stripes[0].physical, blocksize);
        }
 
-       length = blocksize;
-       ret = btrfs_map_block(&root->fs_info->mapping_tree, READ,
-                             bytenr, &length, &multi, 0, NULL);
-       BUG_ON(ret);
-       device = multi->stripes[0].dev;
-       device->total_ios++;
-       blocksize = min(blocksize, (u32)(64 * 1024));
-       readahead(device->fd, multi->stripes[0].physical, blocksize);
+       free_extent_buffer(eb);
        kfree(multi);
-       return 0;
 }
 
 static int verify_parent_transid(struct extent_io_tree *io_tree,
@@ -206,7 +202,8 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr
                read_len = bytes_left;
                device = NULL;
 
-               if (!info->on_restoring) {
+               if (!info->on_restoring &&
+                   eb->start != BTRFS_SUPER_INFO_OFFSET) {
                        ret = btrfs_map_block(&info->mapping_tree, READ,
                                              eb->start + offset, &read_len, &multi,
                                              mirror, NULL);
@@ -478,6 +475,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        if (root->commit_root == root->node)
                goto commit_tree;
+       if (root == root->fs_info->tree_root)
+               goto commit_tree;
 
        free_extent_buffer(root->commit_root);
        root->commit_root = NULL;
@@ -633,7 +632,6 @@ struct btrfs_root *btrfs_read_fs_root_no_cache(struct btrfs_fs_info *fs_info,
        memcpy(&root->root_key, location, sizeof(*location));
        ret = 0;
 out:
-       btrfs_release_path(path);
        btrfs_free_path(path);
        if (ret) {
                free(root);
@@ -914,6 +912,13 @@ int btrfs_setup_all_roots(struct btrfs_fs_info *fs_info, u64 root_tree_bytenr,
                printk("Couldn't setup csum tree\n");
                if (!(flags & OPEN_CTREE_PARTIAL))
                        return -EIO;
+               /* do the same thing as extent tree rebuilding */
+               fs_info->csum_root->node =
+                       btrfs_find_create_tree_block(fs_info->extent_root, 0,
+                                                    leafsize);
+               if (!fs_info->csum_root->node)
+                       return -ENOMEM;
+               clear_extent_buffer_uptodate(NULL, fs_info->csum_root->node);
        }
        fs_info->csum_root->track_dirty = 1;
 
@@ -992,7 +997,7 @@ 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 run_ioctl, int super_recover)
+                         u64 sb_bytenr, int super_recover)
 {
        u64 total_devs;
        int ret;
@@ -1007,7 +1012,7 @@ int btrfs_scan_fs_devices(int fd, const char *path,
        }
 
        if (total_devs != 1) {
-               ret = btrfs_scan_for_fsid(run_ioctl);
+               ret = btrfs_scan_lblkid(!BTRFS_UPDATE_KERNEL);
                if (ret)
                        return ret;
        }
@@ -1088,7 +1093,6 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
                fs_info->on_restoring = 1;
 
        ret = btrfs_scan_fs_devices(fp, path, &fs_devices, sb_bytenr,
-                                   !(flags & OPEN_CTREE_RECOVER_SUPER),
                                    (flags & OPEN_CTREE_RECOVER_SUPER));
        if (ret)
                goto out;
@@ -1135,13 +1139,10 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, const char *path,
 
        ret = btrfs_setup_all_roots(fs_info, root_tree_bytenr, flags);
        if (ret)
-               goto out_failed;
+               goto out_chunk;
 
        return fs_info;
 
-out_failed:
-       if (flags & OPEN_CTREE_PARTIAL)
-               return fs_info;
 out_chunk:
        btrfs_release_all_roots(fs_info);
        btrfs_cleanup_all_caches(fs_info);