Patch "btrfs: call __btrfs_remove_free_space_cache_locked on cache load failure" has been added to the 6.0-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    btrfs: call __btrfs_remove_free_space_cache_locked on cache load failure

to the 6.0-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     btrfs-call-__btrfs_remove_free_space_cache_locked-on.patch
and it can be found in the queue-6.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit f405bb590036e32502c7d4698281340aab21f78d
Author: Josef Bacik <josef@xxxxxxxxxxxxxx>
Date:   Mon Aug 8 16:10:26 2022 -0400

    btrfs: call __btrfs_remove_free_space_cache_locked on cache load failure
    
    [ Upstream commit 8a1ae2781dee9fc21ca82db682d37bea4bd074ad ]
    
    Now that lockdep is staying enabled through our entire CI runs I started
    seeing the following stack in generic/475
    
    ------------[ cut here ]------------
    WARNING: CPU: 1 PID: 2171864 at fs/btrfs/discard.c:604 btrfs_discard_update_discardable+0x98/0xb0
    CPU: 1 PID: 2171864 Comm: kworker/u4:0 Not tainted 5.19.0-rc8+ #789
    Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
    Workqueue: btrfs-cache btrfs_work_helper
    RIP: 0010:btrfs_discard_update_discardable+0x98/0xb0
    RSP: 0018:ffffb857c2f7bad0 EFLAGS: 00010246
    RAX: 0000000000000000 RBX: ffff8c85c605c200 RCX: 0000000000000001
    RDX: 0000000000000000 RSI: ffffffff86807c5b RDI: ffffffff868a831e
    RBP: ffff8c85c4c54000 R08: 0000000000000000 R09: 0000000000000000
    R10: ffff8c85c66932f0 R11: 0000000000000001 R12: ffff8c85c3899010
    R13: ffff8c85d5be4f40 R14: ffff8c85c4c54000 R15: ffff8c86114bfa80
    FS:  0000000000000000(0000) GS:ffff8c863bd00000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00007f2e7f168160 CR3: 000000010289a004 CR4: 0000000000370ee0
    Call Trace:
    
     __btrfs_remove_free_space_cache+0x27/0x30
     load_free_space_cache+0xad2/0xaf0
     caching_thread+0x40b/0x650
     ? lock_release+0x137/0x2d0
     btrfs_work_helper+0xf2/0x3e0
     ? lock_is_held_type+0xe2/0x140
     process_one_work+0x271/0x590
     ? process_one_work+0x590/0x590
     worker_thread+0x52/0x3b0
     ? process_one_work+0x590/0x590
     kthread+0xf0/0x120
     ? kthread_complete_and_exit+0x20/0x20
     ret_from_fork+0x1f/0x30
    
    This is the code
    
            ctl = block_group->free_space_ctl;
            discard_ctl = &block_group->fs_info->discard_ctl;
    
            lockdep_assert_held(&ctl->tree_lock);
    
    We have a temporary free space ctl for loading the free space cache in
    order to avoid having allocations happening while we're loading the
    cache.  When we hit an error we free it all up, however this also calls
    btrfs_discard_update_discardable, which requires
    block_group->free_space_ctl->tree_lock to be held.  However this is our
    temporary ctl so this lock isn't held.  Fix this by calling
    __btrfs_remove_free_space_cache_locked instead so that we only clean up
    the entries and do not mess with the discardable stats.
    
    Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
    Signed-off-by: David Sterba <dsterba@xxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 835071fa39a9..2f88053cfc5e 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -48,6 +48,25 @@ static void bitmap_clear_bits(struct btrfs_free_space_ctl *ctl,
 			      struct btrfs_free_space *info, u64 offset,
 			      u64 bytes, bool update_stats);
 
+static void __btrfs_remove_free_space_cache_locked(
+				struct btrfs_free_space_ctl *ctl)
+{
+	struct btrfs_free_space *info;
+	struct rb_node *node;
+
+	while ((node = rb_last(&ctl->free_space_offset)) != NULL) {
+		info = rb_entry(node, struct btrfs_free_space, offset_index);
+		if (!info->bitmap) {
+			unlink_free_space(ctl, info, true);
+			kmem_cache_free(btrfs_free_space_cachep, info);
+		} else {
+			free_bitmap(ctl, info);
+		}
+
+		cond_resched_lock(&ctl->tree_lock);
+	}
+}
+
 static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
 					       struct btrfs_path *path,
 					       u64 offset)
@@ -881,7 +900,14 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
 	return ret;
 free_cache:
 	io_ctl_drop_pages(&io_ctl);
-	__btrfs_remove_free_space_cache(ctl);
+
+	/*
+	 * We need to call the _locked variant so we don't try to update the
+	 * discard counters.
+	 */
+	spin_lock(&ctl->tree_lock);
+	__btrfs_remove_free_space_cache_locked(ctl);
+	spin_unlock(&ctl->tree_lock);
 	goto out;
 }
 
@@ -1017,7 +1043,13 @@ int load_free_space_cache(struct btrfs_block_group *block_group)
 		if (ret == 0)
 			ret = 1;
 	} else {
+		/*
+		 * We need to call the _locked variant so we don't try to update
+		 * the discard counters.
+		 */
+		spin_lock(&tmp_ctl.tree_lock);
 		__btrfs_remove_free_space_cache(&tmp_ctl);
+		spin_unlock(&tmp_ctl.tree_lock);
 		btrfs_warn(fs_info,
 			   "block group %llu has wrong amount of free space",
 			   block_group->start);
@@ -2980,25 +3012,6 @@ static void __btrfs_return_cluster_to_free_space(
 	btrfs_put_block_group(block_group);
 }
 
-static void __btrfs_remove_free_space_cache_locked(
-				struct btrfs_free_space_ctl *ctl)
-{
-	struct btrfs_free_space *info;
-	struct rb_node *node;
-
-	while ((node = rb_last(&ctl->free_space_offset)) != NULL) {
-		info = rb_entry(node, struct btrfs_free_space, offset_index);
-		if (!info->bitmap) {
-			unlink_free_space(ctl, info, true);
-			kmem_cache_free(btrfs_free_space_cachep, info);
-		} else {
-			free_bitmap(ctl, info);
-		}
-
-		cond_resched_lock(&ctl->tree_lock);
-	}
-}
-
 void __btrfs_remove_free_space_cache(struct btrfs_free_space_ctl *ctl)
 {
 	spin_lock(&ctl->tree_lock);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux