Merge tag 'siox/for-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ukleine...
[linux-2.6-microblaze.git] / fs / btrfs / disk-io.c
index e71ef97..3df5477 100644 (file)
@@ -29,7 +29,6 @@
 #include "tree-log.h"
 #include "free-space-cache.h"
 #include "free-space-tree.h"
-#include "rcu-string.h"
 #include "dev-replace.h"
 #include "raid56.h"
 #include "sysfs.h"
@@ -193,7 +192,7 @@ static int btrfs_repair_eb_io_failure(const struct extent_buffer *eb,
                struct folio *folio = eb->folios[i];
                u64 start = max_t(u64, eb->start, folio_pos(folio));
                u64 end = min_t(u64, eb->start + eb->len,
-                               folio_pos(folio) + folio_size(folio));
+                               folio_pos(folio) + eb->folio_size);
                u32 len = end - start;
 
                ret = btrfs_repair_io_failure(fs_info, 0, start, len,
@@ -498,15 +497,15 @@ static int btree_migrate_folio(struct address_space *mapping,
 static int btree_writepages(struct address_space *mapping,
                            struct writeback_control *wbc)
 {
-       struct btrfs_fs_info *fs_info;
        int ret;
 
        if (wbc->sync_mode == WB_SYNC_NONE) {
+               struct btrfs_fs_info *fs_info;
 
                if (wbc->for_kupdate)
                        return 0;
 
-               fs_info = BTRFS_I(mapping->host)->root->fs_info;
+               fs_info = inode_to_fs_info(mapping->host);
                /* this is a bit racy, but that's ok */
                ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes,
                                             BTRFS_DIRTY_METADATA_THRESH,
@@ -529,11 +528,12 @@ static void btree_invalidate_folio(struct folio *folio, size_t offset,
                                 size_t length)
 {
        struct extent_io_tree *tree;
-       tree = &BTRFS_I(folio->mapping->host)->io_tree;
+
+       tree = &folio_to_inode(folio)->io_tree;
        extent_invalidate_folio(tree, folio, offset);
        btree_release_folio(folio, GFP_NOFS);
        if (folio_get_private(folio)) {
-               btrfs_warn(BTRFS_I(folio->mapping->host)->root->fs_info,
+               btrfs_warn(folio_to_fs_info(folio),
                           "folio private not zero on folio %llu",
                           (unsigned long long)folio_pos(folio));
                folio_detach_private(folio);
@@ -544,7 +544,7 @@ static void btree_invalidate_folio(struct folio *folio, size_t offset,
 static bool btree_dirty_folio(struct address_space *mapping,
                struct folio *folio)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(mapping->host->i_sb);
+       struct btrfs_fs_info *fs_info = inode_to_fs_info(mapping->host);
        struct btrfs_subpage_info *spi = fs_info->subpage_info;
        struct btrfs_subpage *subpage;
        struct extent_buffer *eb;
@@ -1244,6 +1244,7 @@ void btrfs_check_leaked_roots(struct btrfs_fs_info *fs_info)
                btrfs_err(fs_info, "leaked root %s refcount %d",
                          btrfs_root_name(&root->root_key, buf),
                          refcount_read(&root->refs));
+               WARN_ON_ONCE(1);
                while (refcount_read(&root->refs) > 1)
                        btrfs_put_root(root);
                btrfs_put_root(root);
@@ -1307,12 +1308,12 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
  *
  * @objectid:  root id
  * @anon_dev:  preallocated anonymous block device number for new roots,
- *             pass 0 for new allocation.
+ *             pass NULL for a new allocation.
  * @check_ref: whether to check root item references, If true, return -ENOENT
  *             for orphan roots
  */
 static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
-                                            u64 objectid, dev_t anon_dev,
+                                            u64 objectid, dev_t *anon_dev,
                                             bool check_ref)
 {
        struct btrfs_root *root;
@@ -1342,9 +1343,9 @@ again:
                 * that common but still possible.  In that case, we just need
                 * to free the anon_dev.
                 */
-               if (unlikely(anon_dev)) {
-                       free_anon_bdev(anon_dev);
-                       anon_dev = 0;
+               if (unlikely(anon_dev && *anon_dev)) {
+                       free_anon_bdev(*anon_dev);
+                       *anon_dev = 0;
                }
 
                if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
@@ -1366,7 +1367,7 @@ again:
                goto fail;
        }
 
-       ret = btrfs_init_fs_root(root, anon_dev);
+       ret = btrfs_init_fs_root(root, anon_dev ? *anon_dev : 0);
        if (ret)
                goto fail;
 
@@ -1402,7 +1403,7 @@ fail:
         * root's anon_dev to 0 to avoid a double free, once by btrfs_put_root()
         * and once again by our caller.
         */
-       if (anon_dev)
+       if (anon_dev && *anon_dev)
                root->anon_dev = 0;
        btrfs_put_root(root);
        return ERR_PTR(ret);
@@ -1418,7 +1419,7 @@ fail:
 struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
                                     u64 objectid, bool check_ref)
 {
-       return btrfs_get_root_ref(fs_info, objectid, 0, check_ref);
+       return btrfs_get_root_ref(fs_info, objectid, NULL, check_ref);
 }
 
 /*
@@ -1426,11 +1427,11 @@ struct btrfs_root *btrfs_get_fs_root(struct btrfs_fs_info *fs_info,
  * the anonymous block device id
  *
  * @objectid:  tree objectid
- * @anon_dev:  if zero, allocate a new anonymous block device or use the
- *             parameter value
+ * @anon_dev:  if NULL, allocate a new anonymous block device or use the
+ *             parameter value if not NULL
  */
 struct btrfs_root *btrfs_get_new_fs_root(struct btrfs_fs_info *fs_info,
-                                        u64 objectid, dev_t anon_dev)
+                                        u64 objectid, dev_t *anon_dev)
 {
        return btrfs_get_root_ref(fs_info, objectid, anon_dev, true);
 }
@@ -2239,7 +2240,7 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
        struct btrfs_key location;
        int ret;
 
-       BUG_ON(!fs_info->tree_root);
+       ASSERT(fs_info->tree_root);
 
        ret = load_global_roots(tree_root);
        if (ret)
@@ -2839,6 +2840,7 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
        int ret;
 
        fs_info->sb = sb;
+       /* Temporary fixed values for block size until we read the superblock. */
        sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE;
        sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE);
 
@@ -3356,6 +3358,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
        sb->s_bdi->ra_pages *= btrfs_super_num_devices(disk_super);
        sb->s_bdi->ra_pages = max(sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
 
+       /* Update the values for the current filesystem. */
        sb->s_blocksize = sectorsize;
        sb->s_blocksize_bits = blksize_bits(sectorsize);
        memcpy(&sb->s_uuid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE);
@@ -4626,7 +4629,7 @@ static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
                struct inode *inode = NULL;
                btrfs_inode = list_first_entry(&splice, struct btrfs_inode,
                                               delalloc_inodes);
-               __btrfs_del_delalloc_inode(root, btrfs_inode);
+               btrfs_del_delalloc_inode(btrfs_inode);
                spin_unlock(&root->delalloc_lock);
 
                /*
@@ -4925,7 +4928,14 @@ int btrfs_init_root_free_objectid(struct btrfs_root *root)
        ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
        if (ret < 0)
                goto error;
-       BUG_ON(ret == 0); /* Corruption */
+       if (ret == 0) {
+               /*
+                * Key with offset -1 found, there would have to exist a root
+                * with such id, but this is out of valid range.
+                */
+               ret = -EUCLEAN;
+               goto error;
+       }
        if (path->slots[0] > 0) {
                slot = path->slots[0] - 1;
                l = path->nodes[0];