diff options
author | Chris Mason <clm@fb.com> | 2015-04-01 18:36:05 +0300 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-04-01 18:36:05 +0300 |
commit | dd82525956744c3a5e6b7275cd468b6180cc5b72 (patch) | |
tree | bfe24f8600c25306d8ddccbc144f766b1d9a2ad0 /fs/btrfs | |
parent | e56a951e01bf55f49533c47ad2ce61dbd613a3f3 (diff) | |
download | linux-dd82525956744c3a5e6b7275cd468b6180cc5b72.tar.xz |
Btrfs: free and unlock our path before btrfs_free_and_pin_reserved_extent()
The error handling path for alloc_reserved_tree_block is calling
btrfs_free_and_pin_reserved_extent with a spinning tree lock held. This
might sleep as we allocate extent_state objects:
BUG: sleeping function called from invalid context at mm/slub.c:1268
in_atomic(): 1, irqs_disabled(): 0, pid: 11093, name: kworker/u4:7
5 locks held by kworker/u4:7/11093:
#0: ("%s-%s""btrfs", name){++++.+}, at: [<ffffffff81091d51>] process_one_work+0x151/0x520
#1: ((&work->normal_work)){+.+.+.}, at: [<ffffffff81091d51>] process_one_work+0x151/0x520
#2: (sb_internal){++++.+}, at: [<ffffffffa003a70e>] start_transaction+0x43e/0x590 [btrfs]
#3: (&head_ref->mutex){+.+...}, at: [<ffffffffa0089f8c>] btrfs_delayed_ref_lock+0x4c/0x240 [btrfs]
#4: (btrfs-extent-00){++++..}, at: [<ffffffffa007697b>] btrfs_clear_lock_blocking_rw+0x9b/0x150 [btrfs]
CPU: 0 PID: 11093 Comm: kworker/u4:7 Tainted: G W 4.0.0-rc6-default+ #246
Hardware name: Intel Corporation Santa Rosa platform/Matanzas, BIOS TSRSCRB1.86C.0047.B00.0610170821 10/17/06
Workqueue: btrfs-extent-refs btrfs_extent_refs_helper [btrfs]
00000000000004f4 ffff88006dd17848 ffffffff81ab0e3b ffff88006dd17848
ffff88007a944760 ffff88006dd17868 ffffffff8109d516 ffff88006dd17898
0000000000000000 ffff88006dd17898 ffffffff8109d5b2 ffffffff81aba2bb
Call Trace:
[<ffffffff81ab0e3b>] dump_stack+0x4f/0x6c
[<ffffffff8109d516>] ___might_sleep+0xf6/0x140
[<ffffffff8109d5b2>] __might_sleep+0x52/0x90
[<ffffffff81aba2bb>] ? ftrace_call+0x5/0x34
[<ffffffff81196363>] kmem_cache_alloc+0x163/0x1b0
[<ffffffffa0056f31>] ? alloc_extent_state+0x31/0x150 [btrfs]
[<ffffffffa0056f20>] ? alloc_extent_state+0x20/0x150 [btrfs]
[<ffffffffa0056f31>] alloc_extent_state+0x31/0x150 [btrfs]
[<ffffffffa005805b>] __set_extent_bit+0x37b/0x5d0 [btrfs]
[<ffffffff81aba2bb>] ? ftrace_call+0x5/0x34
[<ffffffffa005888d>] ? set_extent_bit+0xd/0x30 [btrfs]
[<ffffffffa00588a3>] set_extent_bit+0x23/0x30 [btrfs]
[<ffffffffa0058e80>] set_extent_dirty+0x20/0x30 [btrfs]
[<ffffffffa00195ba>] pin_down_extent+0xaa/0x170 [btrfs]
[<ffffffffa001d8ef>] __btrfs_free_reserved_extent+0xcf/0x160 [btrfs]
[<ffffffffa0023856>] btrfs_free_and_pin_reserved_extent+0x16/0x20 [btrfs]
[<ffffffffa002482a>] __btrfs_run_delayed_refs+0xfca/0x1290 [btrfs]
[<ffffffffa0026eae>] btrfs_run_delayed_refs+0x6e/0x2e0 [btrfs]
[<ffffffffa0027378>] delayed_ref_async_start+0x48/0xb0 [btrfs]
[<ffffffffa006c883>] normal_work_helper+0x83/0x350 [btrfs]
[<ffffffffa006cd79>] ? btrfs_extent_refs_helper+0x9/0x20 [btrfs]
[<ffffffffa006cd82>] btrfs_extent_refs_helper+0x12/0x20 [btrfs]
[<ffffffff81091dcb>] process_one_work+0x1cb/0x520
[<ffffffff81091d51>] ? process_one_work+0x151/0x520
[<ffffffff811c7abf>] ? seq_read+0x3f/0x400
[<ffffffff8109260b>] worker_thread+0x5b/0x4e0
[<ffffffff81097be2>] ? __kthread_parkme+0x12/0xa0
[<ffffffff810925b0>] ? rescuer_thread+0x450/0x450
[<ffffffff81098686>] kthread+0xf6/0x120
[<ffffffff81098590>] ? flush_kthread_worker+0x1b0/0x1b0
[<ffffffff81ab8088>] ret_from_fork+0x58/0x90
[<ffffffff81098590>] ? flush_kthread_worker+0x1b0/0x1b0
------------[ cut here ]------------
This changes things to free the path first, which will also unlock the
extent buffer.
Signed-off-by: Chris Mason <clm@fb.com>
Reported-by: Dave Sterba <dsterba@suse.cz>
Tested-by: Dave Sterba <dsterba@suse.cz>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 62fa6049e5b6..41e5812c131f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -7093,9 +7093,9 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path, ins, size); if (ret) { + btrfs_free_path(path); btrfs_free_and_pin_reserved_extent(root, ins->objectid, root->nodesize); - btrfs_free_path(path); return ret; } |