diff options
Diffstat (limited to '0001-btrfs-drop-logs-when-we-ve-aborted-a-transaction.patch')
-rw-r--r-- | 0001-btrfs-drop-logs-when-we-ve-aborted-a-transaction.patch | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/0001-btrfs-drop-logs-when-we-ve-aborted-a-transaction.patch b/0001-btrfs-drop-logs-when-we-ve-aborted-a-transaction.patch new file mode 100644 index 000000000..797cd956e --- /dev/null +++ b/0001-btrfs-drop-logs-when-we-ve-aborted-a-transaction.patch @@ -0,0 +1,150 @@ +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 + |