]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - fs/btrfs/disk-io.c
btrfs: replace readpage_end_io_hook with direct calls
[mirror_ubuntu-jammy-kernel.git] / fs / btrfs / disk-io.c
index 9f72b092bc2281c95f45a5f73cff86c14b26c0e7..1c84a7ea9894e1f5d25451b67ea72a54b2d499c3 100644 (file)
@@ -204,53 +204,6 @@ void btrfs_set_buffer_lockdep_class(u64 objectid, struct extent_buffer *eb,
 
 #endif
 
-/*
- * extents on the btree inode are pretty simple, there's one extent
- * that covers the entire device
- */
-struct extent_map *btree_get_extent(struct btrfs_inode *inode,
-                                   struct page *page, size_t pg_offset,
-                                   u64 start, u64 len)
-{
-       struct extent_map_tree *em_tree = &inode->extent_tree;
-       struct extent_map *em;
-       int ret;
-
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, start, len);
-       if (em) {
-               read_unlock(&em_tree->lock);
-               goto out;
-       }
-       read_unlock(&em_tree->lock);
-
-       em = alloc_extent_map();
-       if (!em) {
-               em = ERR_PTR(-ENOMEM);
-               goto out;
-       }
-       em->start = 0;
-       em->len = (u64)-1;
-       em->block_len = (u64)-1;
-       em->block_start = 0;
-
-       write_lock(&em_tree->lock);
-       ret = add_extent_mapping(em_tree, em, 0);
-       if (ret == -EEXIST) {
-               free_extent_map(em);
-               em = lookup_extent_mapping(em_tree, start, len);
-               if (!em)
-                       em = ERR_PTR(-EIO);
-       } else if (ret) {
-               free_extent_map(em);
-               em = ERR_PTR(ret);
-       }
-       write_unlock(&em_tree->lock);
-
-out:
-       return em;
-}
-
 /*
  * Compute the csum of a btree block and store the result to provided buffer.
  */
@@ -545,38 +498,35 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page)
 static int check_tree_block_fsid(struct extent_buffer *eb)
 {
        struct btrfs_fs_info *fs_info = eb->fs_info;
-       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices, *seed_devs;
        u8 fsid[BTRFS_FSID_SIZE];
-       int ret = 1;
+       u8 *metadata_uuid;
 
        read_extent_buffer(eb, fsid, offsetof(struct btrfs_header, fsid),
                           BTRFS_FSID_SIZE);
-       while (fs_devices) {
-               u8 *metadata_uuid;
+       /*
+        * Checking the incompat flag is only valid for the current fs. For
+        * seed devices it's forbidden to have their uuid changed so reading
+        * ->fsid in this case is fine
+        */
+       if (btrfs_fs_incompat(fs_info, METADATA_UUID))
+               metadata_uuid = fs_devices->metadata_uuid;
+       else
+               metadata_uuid = fs_devices->fsid;
 
-               /*
-                * Checking the incompat flag is only valid for the current
-                * fs. For seed devices it's forbidden to have their uuid
-                * changed so reading ->fsid in this case is fine
-                */
-               if (fs_devices == fs_info->fs_devices &&
-                   btrfs_fs_incompat(fs_info, METADATA_UUID))
-                       metadata_uuid = fs_devices->metadata_uuid;
-               else
-                       metadata_uuid = fs_devices->fsid;
+       if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE))
+               return 0;
 
-               if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE)) {
-                       ret = 0;
-                       break;
-               }
-               fs_devices = fs_devices->seed;
-       }
-       return ret;
+       list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list)
+               if (!memcmp(fsid, seed_devs->fsid, BTRFS_FSID_SIZE))
+                       return 0;
+
+       return 1;
 }
 
-static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
-                                     u64 phy_offset, struct page *page,
-                                     u64 start, u64 end, int mirror)
+int btrfs_validate_metadata_buffer(struct btrfs_io_bio *io_bio, u64 phy_offset,
+                                  struct page *page, u64 start, u64 end,
+                                  int mirror)
 {
        u64 found_start;
        int found_level;
@@ -951,11 +901,6 @@ static int btree_writepages(struct address_space *mapping,
        return btree_write_cache_pages(mapping, wbc);
 }
 
-static int btree_readpage(struct file *file, struct page *page)
-{
-       return extent_read_full_page(page, btree_get_extent, 0);
-}
-
 static int btree_releasepage(struct page *page, gfp_t gfp_flags)
 {
        if (PageWriteback(page) || PageDirty(page))
@@ -995,7 +940,6 @@ static int btree_set_page_dirty(struct page *page)
 }
 
 static const struct address_space_operations btree_aops = {
-       .readpage       = btree_readpage,
        .writepages     = btree_writepages,
        .releasepage    = btree_releasepage,
        .invalidatepage = btree_invalidatepage,
@@ -1208,7 +1152,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
        root->root_key.type = BTRFS_ROOT_ITEM_KEY;
        root->root_key.offset = 0;
 
-       leaf = btrfs_alloc_tree_block(trans, root, 0, objectid, NULL, 0, 0, 0);
+       leaf = btrfs_alloc_tree_block(trans, root, 0, objectid, NULL, 0, 0, 0,
+                                     BTRFS_NESTING_NORMAL);
        if (IS_ERR(leaf)) {
                ret = PTR_ERR(leaf);
                leaf = NULL;
@@ -1280,7 +1225,7 @@ static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
         */
 
        leaf = btrfs_alloc_tree_block(trans, root, 0, BTRFS_TREE_LOG_OBJECTID,
-                       NULL, 0, 0, 0);
+                       NULL, 0, 0, 0, BTRFS_NESTING_NORMAL);
        if (IS_ERR(leaf)) {
                btrfs_put_root(root);
                return ERR_CAST(leaf);
@@ -1505,10 +1450,12 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
        struct btrfs_root *root;
 
        while (!list_empty(&fs_info->allocated_roots)) {
+               char buf[BTRFS_ROOT_NAME_BUF_LEN];
+
                root = list_first_entry(&fs_info->allocated_roots,
                                        struct btrfs_root, leak_list);
-               btrfs_err(fs_info, "leaked root %llu-%llu refcount %d",
-                         root->root_key.objectid, root->root_key.offset,
+               btrfs_err(fs_info, "leaked root %s refcount %d",
+                         btrfs_root_name(root->root_key.objectid, buf),
                          refcount_read(&root->refs));
                while (refcount_read(&root->refs) > 1)
                        btrfs_put_root(root);
@@ -2115,7 +2062,7 @@ static void btrfs_init_btree_inode(struct btrfs_fs_info *fs_info)
 
        RB_CLEAR_NODE(&BTRFS_I(inode)->rb_node);
        extent_io_tree_init(fs_info, &BTRFS_I(inode)->io_tree,
-                           IO_TREE_INODE_IO, inode);
+                           IO_TREE_BTREE_INODE_IO, inode);
        BTRFS_I(inode)->io_tree.track_uptodate = false;
        extent_map_tree_init(&BTRFS_I(inode)->extent_tree);
 
@@ -2626,18 +2573,17 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
                level = btrfs_super_root_level(sb);
                tree_root->node = read_tree_block(fs_info, btrfs_super_root(sb),
                                                  generation, level, NULL);
-               if (IS_ERR(tree_root->node) ||
-                   !extent_buffer_uptodate(tree_root->node)) {
+               if (IS_ERR(tree_root->node)) {
                        handle_error = true;
+                       ret = PTR_ERR(tree_root->node);
+                       tree_root->node = NULL;
+                       btrfs_warn(fs_info, "couldn't read tree root");
+                       continue;
 
-                       if (IS_ERR(tree_root->node)) {
-                               ret = PTR_ERR(tree_root->node);
-                               tree_root->node = NULL;
-                       } else if (!extent_buffer_uptodate(tree_root->node)) {
-                               ret = -EUCLEAN;
-                       }
-
-                       btrfs_warn(fs_info, "failed to read tree root");
+               } else if (!extent_buffer_uptodate(tree_root->node)) {
+                       handle_error = true;
+                       ret = -EIO;
+                       btrfs_warn(fs_info, "error while reading tree root");
                        continue;
                }
 
@@ -2753,7 +2699,7 @@ void btrfs_init_fs_info(struct btrfs_fs_info *fs_info)
        fs_info->check_integrity_print_mask = 0;
 #endif
        btrfs_init_balance(fs_info);
-       btrfs_init_async_reclaim_work(&fs_info->async_reclaim_work);
+       btrfs_init_async_reclaim_work(fs_info);
 
        spin_lock_init(&fs_info->block_group_cache_lock);
        fs_info->block_group_cache_tree = RB_ROOT;
@@ -2928,7 +2874,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
        }
 
        /*
-        * Verify the type first, if that or the the checksum value are
+        * Verify the type first, if that or the checksum value are
         * corrupted, we'll find out
         */
        csum_type = btrfs_super_csum_type(disk_super);
@@ -4056,6 +4002,7 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
        btrfs_cleanup_defrag_inodes(fs_info);
 
        cancel_work_sync(&fs_info->async_reclaim_work);
+       cancel_work_sync(&fs_info->async_data_reclaim_work);
 
        /* Cancel or finish ongoing discard work */
        btrfs_discard_cleanup(fs_info);
@@ -4691,5 +4638,5 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
 static const struct extent_io_ops btree_extent_io_ops = {
        /* mandatory callbacks */
        .submit_bio_hook = btree_submit_bio_hook,
-       .readpage_end_io_hook = btree_readpage_end_io_hook,
+       .readpage_end_io_hook = NULL
 };