68dd5fcadc
- 51184ae37e05 rebase Resolves: rhbz# Signed-off-by: Justin M. Forbes <jforbes@fedoraproject.org>
151 lines
5.8 KiB
Diff
151 lines
5.8 KiB
Diff
From ef67963dac255b293e19815ea3d440567be4626f Mon Sep 17 00:00:00 2001
|
|
From: Josef Bacik <josef@toxicpanda.com>
|
|
Date: Tue, 24 Mar 2020 10:47:52 -0400
|
|
Subject: [PATCH] btrfs: drop logs when we've aborted a transaction
|
|
|
|
Dave reported a problem where we were panicing with generic/475 with
|
|
misc-5.7. This is because we were doing IO after we had stopped all of
|
|
the worker threads, because we do the log tree cleanup on roots at drop
|
|
time. Cleaning up the log tree will always need to do reads if we
|
|
happened to have evicted the blocks from memory.
|
|
|
|
Because of this simply add a helper to btrfs_cleanup_transaction() that
|
|
will go through and drop all of the log roots. This gets run before we
|
|
do the close_ctree() work, and thus we are allowed to do any reads that
|
|
we would need. I ran this through many iterations of generic/475 with
|
|
constrained memory and I did not see the issue.
|
|
|
|
general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6b: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI
|
|
CPU: 2 PID: 12359 Comm: umount Tainted: G W 5.6.0-rc7-btrfs-next-58 #1
|
|
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014
|
|
RIP: 0010:btrfs_queue_work+0x33/0x1c0 [btrfs]
|
|
RSP: 0018:ffff9cfb015937d8 EFLAGS: 00010246
|
|
RAX: 0000000000000000 RBX: ffff8eb5e339ed80 RCX: 0000000000000000
|
|
RDX: 0000000000000001 RSI: ffff8eb5eb33b770 RDI: ffff8eb5e37a0460
|
|
RBP: ffff8eb5eb33b770 R08: 000000000000020c R09: ffffffff9fc09ac0
|
|
R10: 0000000000000007 R11: 0000000000000000 R12: 6b6b6b6b6b6b6b6b
|
|
R13: ffff9cfb00229040 R14: 0000000000000008 R15: ffff8eb5d3868000
|
|
FS: 00007f167ea022c0(0000) GS:ffff8eb5fae00000(0000) knlGS:0000000000000000
|
|
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
|
|
CR2: 00007f167e5e0cb1 CR3: 0000000138c18004 CR4: 00000000003606e0
|
|
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
|
|
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
|
|
Call Trace:
|
|
btrfs_end_bio+0x81/0x130 [btrfs]
|
|
__split_and_process_bio+0xaf/0x4e0 [dm_mod]
|
|
? percpu_counter_add_batch+0xa3/0x120
|
|
dm_process_bio+0x98/0x290 [dm_mod]
|
|
? generic_make_request+0xfb/0x410
|
|
dm_make_request+0x4d/0x120 [dm_mod]
|
|
? generic_make_request+0xfb/0x410
|
|
generic_make_request+0x12a/0x410
|
|
? submit_bio+0x38/0x160
|
|
submit_bio+0x38/0x160
|
|
? percpu_counter_add_batch+0xa3/0x120
|
|
btrfs_map_bio+0x289/0x570 [btrfs]
|
|
? kmem_cache_alloc+0x24d/0x300
|
|
btree_submit_bio_hook+0x79/0xc0 [btrfs]
|
|
submit_one_bio+0x31/0x50 [btrfs]
|
|
read_extent_buffer_pages+0x2fe/0x450 [btrfs]
|
|
btree_read_extent_buffer_pages+0x7e/0x170 [btrfs]
|
|
walk_down_log_tree+0x343/0x690 [btrfs]
|
|
? walk_log_tree+0x3d/0x380 [btrfs]
|
|
walk_log_tree+0xf7/0x380 [btrfs]
|
|
? plist_requeue+0xf0/0xf0
|
|
? delete_node+0x4b/0x230
|
|
free_log_tree+0x4c/0x130 [btrfs]
|
|
? wait_log_commit+0x140/0x140 [btrfs]
|
|
btrfs_free_log+0x17/0x30 [btrfs]
|
|
btrfs_drop_and_free_fs_root+0xb0/0xd0 [btrfs]
|
|
btrfs_free_fs_roots+0x10c/0x190 [btrfs]
|
|
? do_raw_spin_unlock+0x49/0xc0
|
|
? _raw_spin_unlock+0x29/0x40
|
|
? release_extent_buffer+0x121/0x170 [btrfs]
|
|
close_ctree+0x289/0x2e6 [btrfs]
|
|
generic_shutdown_super+0x6c/0x110
|
|
kill_anon_super+0xe/0x30
|
|
btrfs_kill_super+0x12/0x20 [btrfs]
|
|
deactivate_locked_super+0x3a/0x70
|
|
|
|
Reported-by: David Sterba <dsterba@suse.com>
|
|
Fixes: 8c38938c7bb096 ("btrfs: move the root freeing stuff into btrfs_put_root")
|
|
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
|
|
Reviewed-by: Filipe Manana <fdmanana@suse.com>
|
|
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
|
|
Signed-off-by: David Sterba <dsterba@suse.com>
|
|
---
|
|
fs/btrfs/disk-io.c | 36 ++++++++++++++++++++++++++++++++----
|
|
1 file changed, 32 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
|
index a6cb5cbbdb9f..d10c7be10f3b 100644
|
|
--- a/fs/btrfs/disk-io.c
|
|
+++ b/fs/btrfs/disk-io.c
|
|
@@ -2036,9 +2036,6 @@ void btrfs_free_fs_roots(struct btrfs_fs_info *fs_info)
|
|
for (i = 0; i < ret; i++)
|
|
btrfs_drop_and_free_fs_root(fs_info, gang[i]);
|
|
}
|
|
-
|
|
- if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state))
|
|
- btrfs_free_log_root_tree(NULL, fs_info);
|
|
}
|
|
|
|
static void btrfs_init_scrub(struct btrfs_fs_info *fs_info)
|
|
@@ -3888,7 +3885,7 @@ void btrfs_drop_and_free_fs_root(struct btrfs_fs_info *fs_info,
|
|
spin_unlock(&fs_info->fs_roots_radix_lock);
|
|
|
|
if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
|
|
- btrfs_free_log(NULL, root);
|
|
+ ASSERT(root->log_root == NULL);
|
|
if (root->reloc_root) {
|
|
btrfs_put_root(root->reloc_root);
|
|
root->reloc_root = NULL;
|
|
@@ -4211,6 +4208,36 @@ static void btrfs_error_commit_super(struct btrfs_fs_info *fs_info)
|
|
up_write(&fs_info->cleanup_work_sem);
|
|
}
|
|
|
|
+static void btrfs_drop_all_logs(struct btrfs_fs_info *fs_info)
|
|
+{
|
|
+ struct btrfs_root *gang[8];
|
|
+ u64 root_objectid = 0;
|
|
+ int ret;
|
|
+
|
|
+ spin_lock(&fs_info->fs_roots_radix_lock);
|
|
+ while ((ret = radix_tree_gang_lookup(&fs_info->fs_roots_radix,
|
|
+ (void **)gang, root_objectid,
|
|
+ ARRAY_SIZE(gang))) != 0) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ret; i++)
|
|
+ gang[i] = btrfs_grab_root(gang[i]);
|
|
+ spin_unlock(&fs_info->fs_roots_radix_lock);
|
|
+
|
|
+ for (i = 0; i < ret; i++) {
|
|
+ if (!gang[i])
|
|
+ continue;
|
|
+ root_objectid = gang[i]->root_key.objectid;
|
|
+ btrfs_free_log(NULL, gang[i]);
|
|
+ btrfs_put_root(gang[i]);
|
|
+ }
|
|
+ root_objectid++;
|
|
+ spin_lock(&fs_info->fs_roots_radix_lock);
|
|
+ }
|
|
+ spin_unlock(&fs_info->fs_roots_radix_lock);
|
|
+ btrfs_free_log_root_tree(NULL, fs_info);
|
|
+}
|
|
+
|
|
static void btrfs_destroy_ordered_extents(struct btrfs_root *root)
|
|
{
|
|
struct btrfs_ordered_extent *ordered;
|
|
@@ -4603,6 +4630,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
|
|
btrfs_destroy_delayed_inodes(fs_info);
|
|
btrfs_assert_delayed_root_empty(fs_info);
|
|
btrfs_destroy_all_delalloc_inodes(fs_info);
|
|
+ btrfs_drop_all_logs(fs_info);
|
|
mutex_unlock(&fs_info->transaction_kthread_mutex);
|
|
|
|
return 0;
|
|
--
|
|
2.26.2
|
|
|