--- /dev/null
+From 5f8ecdce42b6dc54b3ebf0774842a3a2000e9c7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 May 2023 12:04:18 +0100
+Subject: btrfs: fix space cache inconsistency after error loading it from disk
+
+From: Filipe Manana <fdmanana@suse.com>
+
+[ Upstream commit 0004ff15ea26015a0a3a6182dca3b9d1df32e2b7 ]
+
+When loading a free space cache from disk, at __load_free_space_cache(),
+if we fail to insert a bitmap entry, we still increment the number of
+total bitmaps in the btrfs_free_space_ctl structure, which is incorrect
+since we failed to add the bitmap entry. On error we then empty the
+cache by calling __btrfs_remove_free_space_cache(), which will result
+in getting the total bitmaps counter set to 1.
+
+A failure to load a free space cache is not critical, so if a failure
+happens we just rebuild the cache by scanning the extent tree, which
+happens at block-group.c:caching_thread(). Yet the failure will result
+in having the total bitmaps of the btrfs_free_space_ctl always bigger
+by 1 then the number of bitmap entries we have. So fix this by having
+the total bitmaps counter be incremented only if we successfully added
+the bitmap entry.
+
+Fixes: a67509c30079 ("Btrfs: add a io_ctl struct and helpers for dealing with the space cache")
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/free-space-cache.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
+index ba280707d5ec2..4989c60b1df9c 100644
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -794,15 +794,16 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
+ }
+ spin_lock(&ctl->tree_lock);
+ ret = link_free_space(ctl, e);
+- ctl->total_bitmaps++;
+- ctl->op->recalc_thresholds(ctl);
+- spin_unlock(&ctl->tree_lock);
+ if (ret) {
++ spin_unlock(&ctl->tree_lock);
+ btrfs_err(fs_info,
+ "Duplicate entries in free space cache, dumping");
+ kmem_cache_free(btrfs_free_space_cachep, e);
+ goto free_cache;
+ }
++ ctl->total_bitmaps++;
++ ctl->op->recalc_thresholds(ctl);
++ spin_unlock(&ctl->tree_lock);
+ list_add_tail(&e->list, &bitmaps);
+ }
+
+--
+2.39.2
+
--- /dev/null
+From fbe5b786d31288273ee7d210f5aa5a2d96018121 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Nov 2020 15:10:37 +0200
+Subject: btrfs: move btrfs_find_highest_objectid/btrfs_find_free_objectid to
+ disk-io.c
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+[ Upstream commit ec7d6dfd73b2de1c6bc36f832542061b0ca0e0ff ]
+
+Those functions are going to be used even after inode cache is removed
+so moved them to a more appropriate place.
+
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 0004ff15ea26 ("btrfs: fix space cache inconsistency after error loading it from disk")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
+ fs/btrfs/disk-io.h | 2 ++
+ fs/btrfs/inode-map.c | 55 --------------------------------------------
+ fs/btrfs/inode-map.h | 3 ---
+ 4 files changed, 57 insertions(+), 58 deletions(-)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 2a7778a88f03b..095c9e4f92248 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -4780,3 +4780,58 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
+
+ return 0;
+ }
++
++int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
++{
++ struct btrfs_path *path;
++ int ret;
++ struct extent_buffer *l;
++ struct btrfs_key search_key;
++ struct btrfs_key found_key;
++ int slot;
++
++ path = btrfs_alloc_path();
++ if (!path)
++ return -ENOMEM;
++
++ search_key.objectid = BTRFS_LAST_FREE_OBJECTID;
++ search_key.type = -1;
++ search_key.offset = (u64)-1;
++ ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
++ if (ret < 0)
++ goto error;
++ BUG_ON(ret == 0); /* Corruption */
++ if (path->slots[0] > 0) {
++ slot = path->slots[0] - 1;
++ l = path->nodes[0];
++ btrfs_item_key_to_cpu(l, &found_key, slot);
++ *objectid = max_t(u64, found_key.objectid,
++ BTRFS_FIRST_FREE_OBJECTID - 1);
++ } else {
++ *objectid = BTRFS_FIRST_FREE_OBJECTID - 1;
++ }
++ ret = 0;
++error:
++ btrfs_free_path(path);
++ return ret;
++}
++
++int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid)
++{
++ int ret;
++ mutex_lock(&root->objectid_mutex);
++
++ if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
++ btrfs_warn(root->fs_info,
++ "the objectid of root %llu reaches its highest value",
++ root->root_key.objectid);
++ ret = -ENOSPC;
++ goto out;
++ }
++
++ *objectid = ++root->highest_objectid;
++ ret = 0;
++out:
++ mutex_unlock(&root->objectid_mutex);
++ return ret;
++}
+diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
+index 182540bdcea0f..e3b96944ce10c 100644
+--- a/fs/btrfs/disk-io.h
++++ b/fs/btrfs/disk-io.h
+@@ -131,6 +131,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
+ int btree_lock_page_hook(struct page *page, void *data,
+ void (*flush_fn)(void *));
+ int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags);
++int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
++int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid);
+ int __init btrfs_end_io_wq_init(void);
+ void __cold btrfs_end_io_wq_exit(void);
+
+diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
+index 76d2e43817eae..c74340d22624e 100644
+--- a/fs/btrfs/inode-map.c
++++ b/fs/btrfs/inode-map.c
+@@ -525,58 +525,3 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
+ extent_changeset_free(data_reserved);
+ return ret;
+ }
+-
+-int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid)
+-{
+- struct btrfs_path *path;
+- int ret;
+- struct extent_buffer *l;
+- struct btrfs_key search_key;
+- struct btrfs_key found_key;
+- int slot;
+-
+- path = btrfs_alloc_path();
+- if (!path)
+- return -ENOMEM;
+-
+- search_key.objectid = BTRFS_LAST_FREE_OBJECTID;
+- search_key.type = -1;
+- search_key.offset = (u64)-1;
+- ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
+- if (ret < 0)
+- goto error;
+- BUG_ON(ret == 0); /* Corruption */
+- if (path->slots[0] > 0) {
+- slot = path->slots[0] - 1;
+- l = path->nodes[0];
+- btrfs_item_key_to_cpu(l, &found_key, slot);
+- *objectid = max_t(u64, found_key.objectid,
+- BTRFS_FIRST_FREE_OBJECTID - 1);
+- } else {
+- *objectid = BTRFS_FIRST_FREE_OBJECTID - 1;
+- }
+- ret = 0;
+-error:
+- btrfs_free_path(path);
+- return ret;
+-}
+-
+-int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid)
+-{
+- int ret;
+- mutex_lock(&root->objectid_mutex);
+-
+- if (unlikely(root->highest_objectid >= BTRFS_LAST_FREE_OBJECTID)) {
+- btrfs_warn(root->fs_info,
+- "the objectid of root %llu reaches its highest value",
+- root->root_key.objectid);
+- ret = -ENOSPC;
+- goto out;
+- }
+-
+- *objectid = ++root->highest_objectid;
+- ret = 0;
+-out:
+- mutex_unlock(&root->objectid_mutex);
+- return ret;
+-}
+diff --git a/fs/btrfs/inode-map.h b/fs/btrfs/inode-map.h
+index 7a962811dffe0..629baf9aefb15 100644
+--- a/fs/btrfs/inode-map.h
++++ b/fs/btrfs/inode-map.h
+@@ -10,7 +10,4 @@ int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid);
+ int btrfs_save_ino_cache(struct btrfs_root *root,
+ struct btrfs_trans_handle *trans);
+
+-int btrfs_find_free_objectid(struct btrfs_root *root, u64 *objectid);
+-int btrfs_find_highest_objectid(struct btrfs_root *root, u64 *objectid);
+-
+ #endif
+--
+2.39.2
+
--- /dev/null
+From bba8659a23803accf40a26e32750dbd803e23d7c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 26 Nov 2020 15:10:38 +0200
+Subject: btrfs: replace calls to btrfs_find_free_ino with
+ btrfs_find_free_objectid
+
+From: Nikolay Borisov <nborisov@suse.com>
+
+[ Upstream commit abadc1fcd72e887a8f875dabe4a07aa8c28ac8af ]
+
+The former is going away as part of the inode map removal so switch
+callers to btrfs_find_free_objectid. No functional changes since with
+INODE_MAP disabled (default) find_free_objectid was called anyway.
+
+Signed-off-by: Nikolay Borisov <nborisov@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 0004ff15ea26 ("btrfs: fix space cache inconsistency after error loading it from disk")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/inode.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 779b7745cdc48..c900a39666e38 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -6273,7 +6273,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+- err = btrfs_find_free_ino(root, &objectid);
++ err = btrfs_find_free_objectid(root, &objectid);
+ if (err)
+ goto out_unlock;
+
+@@ -6337,7 +6337,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+- err = btrfs_find_free_ino(root, &objectid);
++ err = btrfs_find_free_objectid(root, &objectid);
+ if (err)
+ goto out_unlock;
+
+@@ -6481,7 +6481,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+- err = btrfs_find_free_ino(root, &objectid);
++ err = btrfs_find_free_objectid(root, &objectid);
+ if (err)
+ goto out_fail;
+
+@@ -9135,7 +9135,7 @@ static int btrfs_whiteout_for_rename(struct btrfs_trans_handle *trans,
+ u64 objectid;
+ u64 index;
+
+- ret = btrfs_find_free_ino(root, &objectid);
++ ret = btrfs_find_free_objectid(root, &objectid);
+ if (ret)
+ return ret;
+
+@@ -9631,7 +9631,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+- err = btrfs_find_free_ino(root, &objectid);
++ err = btrfs_find_free_objectid(root, &objectid);
+ if (err)
+ goto out_unlock;
+
+@@ -9962,7 +9962,7 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
+
+- ret = btrfs_find_free_ino(root, &objectid);
++ ret = btrfs_find_free_objectid(root, &objectid);
+ if (ret)
+ goto out;
+
+--
+2.39.2
+