All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Btrfs: fix a bug of sleeping in atomic context
@ 2015-11-20  1:49 Liu Bo
  2015-11-20 13:13 ` Chris Mason
  0 siblings, 1 reply; 11+ messages in thread
From: Liu Bo @ 2015-11-20  1:49 UTC (permalink / raw)
  To: linux-btrfs

while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
so those sub-stripe writes are gatherred into plug callback list and
hopefully we can have a full stripe writes.

However, while processing these plugged callbacks, it's within an atomic
context which is provided by blk_sq_make_request() because of a get_cpu()
in blk_mq_get_ctx().

This changes to always use btrfs_rmw_helper to complete the pending writes.

[1]:

BUG: sleeping function called from invalid context at mm/page_alloc.c:3190
in_atomic(): 1, irqs_disabled(): 0, pid: 6, name: kworker/u16:0
3 locks held by kworker/u16:0/6:
 #0:  ("writeback"){++++.+}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
 #1:  ((&(&wb->dwork)->work)){+.+.+.}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
 #2:  (&type->s_umount_key#44){+++++.}, at: [<ffffffff811e6805>] trylock_super+0x25/0x60
CPU: 5 PID: 6 Comm: kworker/u16:0 Tainted: G           OE   4.3.0+ #3
Hardware name: Red Hat KVM, BIOS Bochs 01/01/2011
Workqueue: writeback wb_workfn (flush-btrfs-108)
 ffffffff81a3abab ffff88042e282ba8 ffffffff8130191b ffffffff81a3abab
 0000000000000c76 ffff88042e282ba8 ffff88042e27c180 ffff88042e282bd8
 ffffffff8108ed95 ffff880400000004 0000000000000000 0000000000000c76
Call Trace:
 [<ffffffff8130191b>] dump_stack+0x4f/0x74
 [<ffffffff8108ed95>] ___might_sleep+0x185/0x240
 [<ffffffff8108eea2>] __might_sleep+0x52/0x90
 [<ffffffff811817e8>] __alloc_pages_nodemask+0x268/0x410
 [<ffffffff8109a43c>] ? sched_clock_local+0x1c/0x90
 [<ffffffff8109a6d1>] ? local_clock+0x21/0x40
 [<ffffffff810b9eb0>] ? __lock_release+0x420/0x510
 [<ffffffff810b534c>] ? __lock_acquired+0x16c/0x3c0
 [<ffffffff811ca265>] alloc_pages_current+0xc5/0x210
 [<ffffffffa0577105>] ? rbio_is_full+0x55/0x70 [btrfs]
 [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
 [<ffffffff81666d50>] ? _raw_spin_unlock_irqrestore+0x40/0x60
 [<ffffffffa0578c0a>] full_stripe_write+0x5a/0xc0 [btrfs]
 [<ffffffffa0578ca9>] __raid56_parity_write+0x39/0x60 [btrfs]
 [<ffffffffa0578deb>] run_plug+0x11b/0x140 [btrfs]
 [<ffffffffa0578e33>] btrfs_raid_unplug+0x23/0x70 [btrfs]
 [<ffffffff812d36c2>] blk_flush_plug_list+0x82/0x1f0
 [<ffffffff812e0349>] blk_sq_make_request+0x1f9/0x740
 [<ffffffff812ceba2>] ? generic_make_request_checks+0x222/0x7c0
 [<ffffffff812cf264>] ? blk_queue_enter+0x124/0x310
 [<ffffffff812cf1d2>] ? blk_queue_enter+0x92/0x310
 [<ffffffff812d0ae2>] generic_make_request+0x172/0x2c0
 [<ffffffff812d0ad4>] ? generic_make_request+0x164/0x2c0
 [<ffffffff812d0ca0>] submit_bio+0x70/0x140
 [<ffffffffa0577b29>] ? rbio_add_io_page+0x99/0x150 [btrfs]
 [<ffffffffa0578a89>] finish_rmw+0x4d9/0x600 [btrfs]
 [<ffffffffa0578c4c>] full_stripe_write+0x9c/0xc0 [btrfs]
 [<ffffffffa057ab7f>] raid56_parity_write+0xef/0x160 [btrfs]
 [<ffffffffa052bd83>] btrfs_map_bio+0xe3/0x2d0 [btrfs]
 [<ffffffffa04fbd6d>] btrfs_submit_bio_hook+0x8d/0x1d0 [btrfs]
 [<ffffffffa05173c4>] submit_one_bio+0x74/0xb0 [btrfs]
 [<ffffffffa0517f55>] submit_extent_page+0xe5/0x1c0 [btrfs]
 [<ffffffffa0519b18>] __extent_writepage_io+0x408/0x4c0 [btrfs]
 [<ffffffffa05179c0>] ? alloc_dummy_extent_buffer+0x140/0x140 [btrfs]
 [<ffffffffa051dc88>] __extent_writepage+0x218/0x3a0 [btrfs]
 [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
 [<ffffffffa051e2c9>] extent_write_cache_pages.clone.0+0x2f9/0x400 [btrfs]
 [<ffffffffa051e422>] extent_writepages+0x52/0x70 [btrfs]
 [<ffffffffa05001f0>] ? btrfs_set_inode_index+0x70/0x70 [btrfs]
 [<ffffffffa04fcc17>] btrfs_writepages+0x27/0x30 [btrfs]
 [<ffffffff81184df3>] do_writepages+0x23/0x40
 [<ffffffff81212229>] __writeback_single_inode+0x89/0x4d0
 [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
 [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
 [<ffffffff8121295f>] ? writeback_sb_inodes+0x15f/0x480
 [<ffffffff81212ad2>] writeback_sb_inodes+0x2d2/0x480
 [<ffffffff810b1397>] ? down_read_trylock+0x57/0x60
 [<ffffffff811e6805>] ? trylock_super+0x25/0x60
 [<ffffffff810d629f>] ? rcu_read_lock_sched_held+0x4f/0x90
 [<ffffffff81212d0c>] __writeback_inodes_wb+0x8c/0xc0
 [<ffffffff812130b5>] wb_writeback+0x2b5/0x500
 [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
 [<ffffffff810660a8>] ? __local_bh_enable_ip+0x68/0xc0
 [<ffffffff81213362>] ? wb_do_writeback+0x62/0x310
 [<ffffffff812133c1>] wb_do_writeback+0xc1/0x310
 [<ffffffff8107c3d9>] ? set_worker_desc+0x79/0x90
 [<ffffffff81213842>] wb_workfn+0x92/0x330
 [<ffffffff8107f133>] process_one_work+0x223/0x730
 [<ffffffff8107f083>] ? process_one_work+0x173/0x730
 [<ffffffff8108035f>] ? worker_thread+0x18f/0x430
 [<ffffffff810802ed>] worker_thread+0x11d/0x430
 [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
 [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
 [<ffffffff810858df>] kthread+0xef/0x110
 [<ffffffff8108f74e>] ? schedule_tail+0x1e/0xd0
 [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
 [<ffffffff816673bf>] ret_from_fork+0x3f/0x70
 [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70

Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
---
 fs/btrfs/raid56.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c
index 1a33d3e..03fcf32 100644
--- a/fs/btrfs/raid56.c
+++ b/fs/btrfs/raid56.c
@@ -1731,14 +1731,11 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
 	struct btrfs_plug_cb *plug;
 	plug = container_of(cb, struct btrfs_plug_cb, cb);
 
-	if (from_schedule) {
-		btrfs_init_work(&plug->work, btrfs_rmw_helper,
-				unplug_work, NULL, NULL);
-		btrfs_queue_work(plug->info->rmw_workers,
-				 &plug->work);
-		return;
-	}
-	run_plug(plug);
+	btrfs_init_work(&plug->work, btrfs_rmw_helper,
+			unplug_work, NULL, NULL);
+	btrfs_queue_work(plug->info->rmw_workers,
+			 &plug->work);
+	return;
 }
 
 /*
-- 
2.5.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20  1:49 [PATCH] Btrfs: fix a bug of sleeping in atomic context Liu Bo
@ 2015-11-20 13:13 ` Chris Mason
  2015-11-20 17:57   ` Liu Bo
  2015-11-20 21:30   ` Jens Axboe
  0 siblings, 2 replies; 11+ messages in thread
From: Chris Mason @ 2015-11-20 13:13 UTC (permalink / raw)
  To: Liu Bo, axboe; +Cc: linux-btrfs

On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> so those sub-stripe writes are gatherred into plug callback list and
> hopefully we can have a full stripe writes.
> 
> However, while processing these plugged callbacks, it's within an atomic
> context which is provided by blk_sq_make_request() because of a get_cpu()
> in blk_mq_get_ctx().
> 
> This changes to always use btrfs_rmw_helper to complete the pending writes.
> 

Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.

Jens?

> [1]:
> 
> BUG: sleeping function called from invalid context at mm/page_alloc.c:3190
> in_atomic(): 1, irqs_disabled(): 0, pid: 6, name: kworker/u16:0
> 3 locks held by kworker/u16:0/6:
>  #0:  ("writeback"){++++.+}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
>  #1:  ((&(&wb->dwork)->work)){+.+.+.}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
>  #2:  (&type->s_umount_key#44){+++++.}, at: [<ffffffff811e6805>] trylock_super+0x25/0x60
> CPU: 5 PID: 6 Comm: kworker/u16:0 Tainted: G           OE   4.3.0+ #3
> Hardware name: Red Hat KVM, BIOS Bochs 01/01/2011
> Workqueue: writeback wb_workfn (flush-btrfs-108)
>  ffffffff81a3abab ffff88042e282ba8 ffffffff8130191b ffffffff81a3abab
>  0000000000000c76 ffff88042e282ba8 ffff88042e27c180 ffff88042e282bd8
>  ffffffff8108ed95 ffff880400000004 0000000000000000 0000000000000c76
> Call Trace:
>  [<ffffffff8130191b>] dump_stack+0x4f/0x74
>  [<ffffffff8108ed95>] ___might_sleep+0x185/0x240
>  [<ffffffff8108eea2>] __might_sleep+0x52/0x90
>  [<ffffffff811817e8>] __alloc_pages_nodemask+0x268/0x410
>  [<ffffffff8109a43c>] ? sched_clock_local+0x1c/0x90
>  [<ffffffff8109a6d1>] ? local_clock+0x21/0x40
>  [<ffffffff810b9eb0>] ? __lock_release+0x420/0x510
>  [<ffffffff810b534c>] ? __lock_acquired+0x16c/0x3c0
>  [<ffffffff811ca265>] alloc_pages_current+0xc5/0x210
>  [<ffffffffa0577105>] ? rbio_is_full+0x55/0x70 [btrfs]
>  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
>  [<ffffffff81666d50>] ? _raw_spin_unlock_irqrestore+0x40/0x60
>  [<ffffffffa0578c0a>] full_stripe_write+0x5a/0xc0 [btrfs]
>  [<ffffffffa0578ca9>] __raid56_parity_write+0x39/0x60 [btrfs]
>  [<ffffffffa0578deb>] run_plug+0x11b/0x140 [btrfs]
>  [<ffffffffa0578e33>] btrfs_raid_unplug+0x23/0x70 [btrfs]
>  [<ffffffff812d36c2>] blk_flush_plug_list+0x82/0x1f0
>  [<ffffffff812e0349>] blk_sq_make_request+0x1f9/0x740
>  [<ffffffff812ceba2>] ? generic_make_request_checks+0x222/0x7c0
>  [<ffffffff812cf264>] ? blk_queue_enter+0x124/0x310
>  [<ffffffff812cf1d2>] ? blk_queue_enter+0x92/0x310
>  [<ffffffff812d0ae2>] generic_make_request+0x172/0x2c0
>  [<ffffffff812d0ad4>] ? generic_make_request+0x164/0x2c0
>  [<ffffffff812d0ca0>] submit_bio+0x70/0x140
>  [<ffffffffa0577b29>] ? rbio_add_io_page+0x99/0x150 [btrfs]
>  [<ffffffffa0578a89>] finish_rmw+0x4d9/0x600 [btrfs]
>  [<ffffffffa0578c4c>] full_stripe_write+0x9c/0xc0 [btrfs]
>  [<ffffffffa057ab7f>] raid56_parity_write+0xef/0x160 [btrfs]
>  [<ffffffffa052bd83>] btrfs_map_bio+0xe3/0x2d0 [btrfs]
>  [<ffffffffa04fbd6d>] btrfs_submit_bio_hook+0x8d/0x1d0 [btrfs]
>  [<ffffffffa05173c4>] submit_one_bio+0x74/0xb0 [btrfs]
>  [<ffffffffa0517f55>] submit_extent_page+0xe5/0x1c0 [btrfs]
>  [<ffffffffa0519b18>] __extent_writepage_io+0x408/0x4c0 [btrfs]
>  [<ffffffffa05179c0>] ? alloc_dummy_extent_buffer+0x140/0x140 [btrfs]
>  [<ffffffffa051dc88>] __extent_writepage+0x218/0x3a0 [btrfs]
>  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
>  [<ffffffffa051e2c9>] extent_write_cache_pages.clone.0+0x2f9/0x400 [btrfs]
>  [<ffffffffa051e422>] extent_writepages+0x52/0x70 [btrfs]
>  [<ffffffffa05001f0>] ? btrfs_set_inode_index+0x70/0x70 [btrfs]
>  [<ffffffffa04fcc17>] btrfs_writepages+0x27/0x30 [btrfs]
>  [<ffffffff81184df3>] do_writepages+0x23/0x40
>  [<ffffffff81212229>] __writeback_single_inode+0x89/0x4d0
>  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
>  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
>  [<ffffffff8121295f>] ? writeback_sb_inodes+0x15f/0x480
>  [<ffffffff81212ad2>] writeback_sb_inodes+0x2d2/0x480
>  [<ffffffff810b1397>] ? down_read_trylock+0x57/0x60
>  [<ffffffff811e6805>] ? trylock_super+0x25/0x60
>  [<ffffffff810d629f>] ? rcu_read_lock_sched_held+0x4f/0x90
>  [<ffffffff81212d0c>] __writeback_inodes_wb+0x8c/0xc0
>  [<ffffffff812130b5>] wb_writeback+0x2b5/0x500
>  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
>  [<ffffffff810660a8>] ? __local_bh_enable_ip+0x68/0xc0
>  [<ffffffff81213362>] ? wb_do_writeback+0x62/0x310
>  [<ffffffff812133c1>] wb_do_writeback+0xc1/0x310
>  [<ffffffff8107c3d9>] ? set_worker_desc+0x79/0x90
>  [<ffffffff81213842>] wb_workfn+0x92/0x330
>  [<ffffffff8107f133>] process_one_work+0x223/0x730
>  [<ffffffff8107f083>] ? process_one_work+0x173/0x730
>  [<ffffffff8108035f>] ? worker_thread+0x18f/0x430
>  [<ffffffff810802ed>] worker_thread+0x11d/0x430
>  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
>  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
>  [<ffffffff810858df>] kthread+0xef/0x110
>  [<ffffffff8108f74e>] ? schedule_tail+0x1e/0xd0
>  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
>  [<ffffffff816673bf>] ret_from_fork+0x3f/0x70
>  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 13:13 ` Chris Mason
@ 2015-11-20 17:57   ` Liu Bo
  2015-11-20 20:06     ` Liu Bo
  2015-11-20 21:30   ` Jens Axboe
  1 sibling, 1 reply; 11+ messages in thread
From: Liu Bo @ 2015-11-20 17:57 UTC (permalink / raw)
  To: Chris Mason; +Cc: axboe, linux-btrfs

On Fri, Nov 20, 2015 at 08:13:58AM -0500, Chris Mason wrote:
> On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> > while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> > so those sub-stripe writes are gatherred into plug callback list and
> > hopefully we can have a full stripe writes.
> > 
> > However, while processing these plugged callbacks, it's within an atomic
> > context which is provided by blk_sq_make_request() because of a get_cpu()
> > in blk_mq_get_ctx().
> > 
> > This changes to always use btrfs_rmw_helper to complete the pending writes.
> > 
> 
> Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.

Yeah, MD also does, but I don't see a way to change mq code at this
stage..

Thanks,

-liubo

> 
> Jens?
> 
> > [1]:
> > 
> > BUG: sleeping function called from invalid context at mm/page_alloc.c:3190
> > in_atomic(): 1, irqs_disabled(): 0, pid: 6, name: kworker/u16:0
> > 3 locks held by kworker/u16:0/6:
> >  #0:  ("writeback"){++++.+}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
> >  #1:  ((&(&wb->dwork)->work)){+.+.+.}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
> >  #2:  (&type->s_umount_key#44){+++++.}, at: [<ffffffff811e6805>] trylock_super+0x25/0x60
> > CPU: 5 PID: 6 Comm: kworker/u16:0 Tainted: G           OE   4.3.0+ #3
> > Hardware name: Red Hat KVM, BIOS Bochs 01/01/2011
> > Workqueue: writeback wb_workfn (flush-btrfs-108)
> >  ffffffff81a3abab ffff88042e282ba8 ffffffff8130191b ffffffff81a3abab
> >  0000000000000c76 ffff88042e282ba8 ffff88042e27c180 ffff88042e282bd8
> >  ffffffff8108ed95 ffff880400000004 0000000000000000 0000000000000c76
> > Call Trace:
> >  [<ffffffff8130191b>] dump_stack+0x4f/0x74
> >  [<ffffffff8108ed95>] ___might_sleep+0x185/0x240
> >  [<ffffffff8108eea2>] __might_sleep+0x52/0x90
> >  [<ffffffff811817e8>] __alloc_pages_nodemask+0x268/0x410
> >  [<ffffffff8109a43c>] ? sched_clock_local+0x1c/0x90
> >  [<ffffffff8109a6d1>] ? local_clock+0x21/0x40
> >  [<ffffffff810b9eb0>] ? __lock_release+0x420/0x510
> >  [<ffffffff810b534c>] ? __lock_acquired+0x16c/0x3c0
> >  [<ffffffff811ca265>] alloc_pages_current+0xc5/0x210
> >  [<ffffffffa0577105>] ? rbio_is_full+0x55/0x70 [btrfs]
> >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> >  [<ffffffff81666d50>] ? _raw_spin_unlock_irqrestore+0x40/0x60
> >  [<ffffffffa0578c0a>] full_stripe_write+0x5a/0xc0 [btrfs]
> >  [<ffffffffa0578ca9>] __raid56_parity_write+0x39/0x60 [btrfs]
> >  [<ffffffffa0578deb>] run_plug+0x11b/0x140 [btrfs]
> >  [<ffffffffa0578e33>] btrfs_raid_unplug+0x23/0x70 [btrfs]
> >  [<ffffffff812d36c2>] blk_flush_plug_list+0x82/0x1f0
> >  [<ffffffff812e0349>] blk_sq_make_request+0x1f9/0x740
> >  [<ffffffff812ceba2>] ? generic_make_request_checks+0x222/0x7c0
> >  [<ffffffff812cf264>] ? blk_queue_enter+0x124/0x310
> >  [<ffffffff812cf1d2>] ? blk_queue_enter+0x92/0x310
> >  [<ffffffff812d0ae2>] generic_make_request+0x172/0x2c0
> >  [<ffffffff812d0ad4>] ? generic_make_request+0x164/0x2c0
> >  [<ffffffff812d0ca0>] submit_bio+0x70/0x140
> >  [<ffffffffa0577b29>] ? rbio_add_io_page+0x99/0x150 [btrfs]
> >  [<ffffffffa0578a89>] finish_rmw+0x4d9/0x600 [btrfs]
> >  [<ffffffffa0578c4c>] full_stripe_write+0x9c/0xc0 [btrfs]
> >  [<ffffffffa057ab7f>] raid56_parity_write+0xef/0x160 [btrfs]
> >  [<ffffffffa052bd83>] btrfs_map_bio+0xe3/0x2d0 [btrfs]
> >  [<ffffffffa04fbd6d>] btrfs_submit_bio_hook+0x8d/0x1d0 [btrfs]
> >  [<ffffffffa05173c4>] submit_one_bio+0x74/0xb0 [btrfs]
> >  [<ffffffffa0517f55>] submit_extent_page+0xe5/0x1c0 [btrfs]
> >  [<ffffffffa0519b18>] __extent_writepage_io+0x408/0x4c0 [btrfs]
> >  [<ffffffffa05179c0>] ? alloc_dummy_extent_buffer+0x140/0x140 [btrfs]
> >  [<ffffffffa051dc88>] __extent_writepage+0x218/0x3a0 [btrfs]
> >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> >  [<ffffffffa051e2c9>] extent_write_cache_pages.clone.0+0x2f9/0x400 [btrfs]
> >  [<ffffffffa051e422>] extent_writepages+0x52/0x70 [btrfs]
> >  [<ffffffffa05001f0>] ? btrfs_set_inode_index+0x70/0x70 [btrfs]
> >  [<ffffffffa04fcc17>] btrfs_writepages+0x27/0x30 [btrfs]
> >  [<ffffffff81184df3>] do_writepages+0x23/0x40
> >  [<ffffffff81212229>] __writeback_single_inode+0x89/0x4d0
> >  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
> >  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
> >  [<ffffffff8121295f>] ? writeback_sb_inodes+0x15f/0x480
> >  [<ffffffff81212ad2>] writeback_sb_inodes+0x2d2/0x480
> >  [<ffffffff810b1397>] ? down_read_trylock+0x57/0x60
> >  [<ffffffff811e6805>] ? trylock_super+0x25/0x60
> >  [<ffffffff810d629f>] ? rcu_read_lock_sched_held+0x4f/0x90
> >  [<ffffffff81212d0c>] __writeback_inodes_wb+0x8c/0xc0
> >  [<ffffffff812130b5>] wb_writeback+0x2b5/0x500
> >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> >  [<ffffffff810660a8>] ? __local_bh_enable_ip+0x68/0xc0
> >  [<ffffffff81213362>] ? wb_do_writeback+0x62/0x310
> >  [<ffffffff812133c1>] wb_do_writeback+0xc1/0x310
> >  [<ffffffff8107c3d9>] ? set_worker_desc+0x79/0x90
> >  [<ffffffff81213842>] wb_workfn+0x92/0x330
> >  [<ffffffff8107f133>] process_one_work+0x223/0x730
> >  [<ffffffff8107f083>] ? process_one_work+0x173/0x730
> >  [<ffffffff8108035f>] ? worker_thread+0x18f/0x430
> >  [<ffffffff810802ed>] worker_thread+0x11d/0x430
> >  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
> >  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
> >  [<ffffffff810858df>] kthread+0xef/0x110
> >  [<ffffffff8108f74e>] ? schedule_tail+0x1e/0xd0
> >  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
> >  [<ffffffff816673bf>] ret_from_fork+0x3f/0x70
> >  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 17:57   ` Liu Bo
@ 2015-11-20 20:06     ` Liu Bo
  2015-11-20 20:09       ` Chris Mason
  0 siblings, 1 reply; 11+ messages in thread
From: Liu Bo @ 2015-11-20 20:06 UTC (permalink / raw)
  To: Chris Mason; +Cc: axboe, linux-btrfs

On Fri, Nov 20, 2015 at 09:57:49AM -0800, Liu Bo wrote:
> On Fri, Nov 20, 2015 at 08:13:58AM -0500, Chris Mason wrote:
> > On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> > > while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> > > so those sub-stripe writes are gatherred into plug callback list and
> > > hopefully we can have a full stripe writes.
> > > 
> > > However, while processing these plugged callbacks, it's within an atomic
> > > context which is provided by blk_sq_make_request() because of a get_cpu()
> > > in blk_mq_get_ctx().
> > > 
> > > This changes to always use btrfs_rmw_helper to complete the pending writes.
> > > 
> > 
> > Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
> 
> Yeah, MD also does, but I don't see a way to change mq code at this
> stage..

Correct it: MD raid5_unplug runs stripes inside a pair of spinlock (conf->device_lock) and moreover, those writes will be forwarded to raid5d to finish the job.

So md raid can run fine within atomic context.

Thanks,

-liubo
> 
> Thanks,
> 
> -liubo
> 
> > 
> > Jens?
> > 
> > > [1]:
> > > 
> > > BUG: sleeping function called from invalid context at mm/page_alloc.c:3190
> > > in_atomic(): 1, irqs_disabled(): 0, pid: 6, name: kworker/u16:0
> > > 3 locks held by kworker/u16:0/6:
> > >  #0:  ("writeback"){++++.+}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
> > >  #1:  ((&(&wb->dwork)->work)){+.+.+.}, at: [<ffffffff8107f083>] process_one_work+0x173/0x730
> > >  #2:  (&type->s_umount_key#44){+++++.}, at: [<ffffffff811e6805>] trylock_super+0x25/0x60
> > > CPU: 5 PID: 6 Comm: kworker/u16:0 Tainted: G           OE   4.3.0+ #3
> > > Hardware name: Red Hat KVM, BIOS Bochs 01/01/2011
> > > Workqueue: writeback wb_workfn (flush-btrfs-108)
> > >  ffffffff81a3abab ffff88042e282ba8 ffffffff8130191b ffffffff81a3abab
> > >  0000000000000c76 ffff88042e282ba8 ffff88042e27c180 ffff88042e282bd8
> > >  ffffffff8108ed95 ffff880400000004 0000000000000000 0000000000000c76
> > > Call Trace:
> > >  [<ffffffff8130191b>] dump_stack+0x4f/0x74
> > >  [<ffffffff8108ed95>] ___might_sleep+0x185/0x240
> > >  [<ffffffff8108eea2>] __might_sleep+0x52/0x90
> > >  [<ffffffff811817e8>] __alloc_pages_nodemask+0x268/0x410
> > >  [<ffffffff8109a43c>] ? sched_clock_local+0x1c/0x90
> > >  [<ffffffff8109a6d1>] ? local_clock+0x21/0x40
> > >  [<ffffffff810b9eb0>] ? __lock_release+0x420/0x510
> > >  [<ffffffff810b534c>] ? __lock_acquired+0x16c/0x3c0
> > >  [<ffffffff811ca265>] alloc_pages_current+0xc5/0x210
> > >  [<ffffffffa0577105>] ? rbio_is_full+0x55/0x70 [btrfs]
> > >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> > >  [<ffffffff81666d50>] ? _raw_spin_unlock_irqrestore+0x40/0x60
> > >  [<ffffffffa0578c0a>] full_stripe_write+0x5a/0xc0 [btrfs]
> > >  [<ffffffffa0578ca9>] __raid56_parity_write+0x39/0x60 [btrfs]
> > >  [<ffffffffa0578deb>] run_plug+0x11b/0x140 [btrfs]
> > >  [<ffffffffa0578e33>] btrfs_raid_unplug+0x23/0x70 [btrfs]
> > >  [<ffffffff812d36c2>] blk_flush_plug_list+0x82/0x1f0
> > >  [<ffffffff812e0349>] blk_sq_make_request+0x1f9/0x740
> > >  [<ffffffff812ceba2>] ? generic_make_request_checks+0x222/0x7c0
> > >  [<ffffffff812cf264>] ? blk_queue_enter+0x124/0x310
> > >  [<ffffffff812cf1d2>] ? blk_queue_enter+0x92/0x310
> > >  [<ffffffff812d0ae2>] generic_make_request+0x172/0x2c0
> > >  [<ffffffff812d0ad4>] ? generic_make_request+0x164/0x2c0
> > >  [<ffffffff812d0ca0>] submit_bio+0x70/0x140
> > >  [<ffffffffa0577b29>] ? rbio_add_io_page+0x99/0x150 [btrfs]
> > >  [<ffffffffa0578a89>] finish_rmw+0x4d9/0x600 [btrfs]
> > >  [<ffffffffa0578c4c>] full_stripe_write+0x9c/0xc0 [btrfs]
> > >  [<ffffffffa057ab7f>] raid56_parity_write+0xef/0x160 [btrfs]
> > >  [<ffffffffa052bd83>] btrfs_map_bio+0xe3/0x2d0 [btrfs]
> > >  [<ffffffffa04fbd6d>] btrfs_submit_bio_hook+0x8d/0x1d0 [btrfs]
> > >  [<ffffffffa05173c4>] submit_one_bio+0x74/0xb0 [btrfs]
> > >  [<ffffffffa0517f55>] submit_extent_page+0xe5/0x1c0 [btrfs]
> > >  [<ffffffffa0519b18>] __extent_writepage_io+0x408/0x4c0 [btrfs]
> > >  [<ffffffffa05179c0>] ? alloc_dummy_extent_buffer+0x140/0x140 [btrfs]
> > >  [<ffffffffa051dc88>] __extent_writepage+0x218/0x3a0 [btrfs]
> > >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> > >  [<ffffffffa051e2c9>] extent_write_cache_pages.clone.0+0x2f9/0x400 [btrfs]
> > >  [<ffffffffa051e422>] extent_writepages+0x52/0x70 [btrfs]
> > >  [<ffffffffa05001f0>] ? btrfs_set_inode_index+0x70/0x70 [btrfs]
> > >  [<ffffffffa04fcc17>] btrfs_writepages+0x27/0x30 [btrfs]
> > >  [<ffffffff81184df3>] do_writepages+0x23/0x40
> > >  [<ffffffff81212229>] __writeback_single_inode+0x89/0x4d0
> > >  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
> > >  [<ffffffff81212a60>] ? writeback_sb_inodes+0x260/0x480
> > >  [<ffffffff8121295f>] ? writeback_sb_inodes+0x15f/0x480
> > >  [<ffffffff81212ad2>] writeback_sb_inodes+0x2d2/0x480
> > >  [<ffffffff810b1397>] ? down_read_trylock+0x57/0x60
> > >  [<ffffffff811e6805>] ? trylock_super+0x25/0x60
> > >  [<ffffffff810d629f>] ? rcu_read_lock_sched_held+0x4f/0x90
> > >  [<ffffffff81212d0c>] __writeback_inodes_wb+0x8c/0xc0
> > >  [<ffffffff812130b5>] wb_writeback+0x2b5/0x500
> > >  [<ffffffff810b7ed8>] ? mark_held_locks+0x78/0xa0
> > >  [<ffffffff810660a8>] ? __local_bh_enable_ip+0x68/0xc0
> > >  [<ffffffff81213362>] ? wb_do_writeback+0x62/0x310
> > >  [<ffffffff812133c1>] wb_do_writeback+0xc1/0x310
> > >  [<ffffffff8107c3d9>] ? set_worker_desc+0x79/0x90
> > >  [<ffffffff81213842>] wb_workfn+0x92/0x330
> > >  [<ffffffff8107f133>] process_one_work+0x223/0x730
> > >  [<ffffffff8107f083>] ? process_one_work+0x173/0x730
> > >  [<ffffffff8108035f>] ? worker_thread+0x18f/0x430
> > >  [<ffffffff810802ed>] worker_thread+0x11d/0x430
> > >  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
> > >  [<ffffffff810801d0>] ? maybe_create_worker+0xf0/0xf0
> > >  [<ffffffff810858df>] kthread+0xef/0x110
> > >  [<ffffffff8108f74e>] ? schedule_tail+0x1e/0xd0
> > >  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
> > >  [<ffffffff816673bf>] ret_from_fork+0x3f/0x70
> > >  [<ffffffff810857f0>] ? __init_kthread_worker+0x70/0x70
> > 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 20:06     ` Liu Bo
@ 2015-11-20 20:09       ` Chris Mason
  0 siblings, 0 replies; 11+ messages in thread
From: Chris Mason @ 2015-11-20 20:09 UTC (permalink / raw)
  To: Liu Bo; +Cc: axboe, linux-btrfs

On Fri, Nov 20, 2015 at 12:06:33PM -0800, Liu Bo wrote:
> On Fri, Nov 20, 2015 at 09:57:49AM -0800, Liu Bo wrote:
> > On Fri, Nov 20, 2015 at 08:13:58AM -0500, Chris Mason wrote:
> > > On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> > > > while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> > > > so those sub-stripe writes are gatherred into plug callback list and
> > > > hopefully we can have a full stripe writes.
> > > > 
> > > > However, while processing these plugged callbacks, it's within an atomic
> > > > context which is provided by blk_sq_make_request() because of a get_cpu()
> > > > in blk_mq_get_ctx().
> > > > 
> > > > This changes to always use btrfs_rmw_helper to complete the pending writes.
> > > > 
> > > 
> > > Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
> > 
> > Yeah, MD also does, but I don't see a way to change mq code at this
> > stage..
> 
> Correct it: MD raid5_unplug runs stripes inside a pair of spinlock (conf->device_lock) and moreover, those writes will be forwarded to raid5d to finish the job.
> 
> So md raid can run fine within atomic context.

Check MD raid10

-chris

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 13:13 ` Chris Mason
  2015-11-20 17:57   ` Liu Bo
@ 2015-11-20 21:30   ` Jens Axboe
  2015-11-20 23:08     ` Liu Bo
  1 sibling, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2015-11-20 21:30 UTC (permalink / raw)
  To: Chris Mason, Liu Bo, linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 1015 bytes --]

On 11/20/2015 06:13 AM, Chris Mason wrote:
> On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
>> while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
>> so those sub-stripe writes are gatherred into plug callback list and
>> hopefully we can have a full stripe writes.
>>
>> However, while processing these plugged callbacks, it's within an atomic
>> context which is provided by blk_sq_make_request() because of a get_cpu()
>> in blk_mq_get_ctx().
>>
>> This changes to always use btrfs_rmw_helper to complete the pending writes.
>>
>
> Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
>
> Jens?

Yeah, blk-mq does have preemption disabled when it flushes, for the 
single queue setup. That's a bug. Attached is an untested patch that 
should fix it, can you try it?

I'll rework this to be a proper patch, not convinced we want to add the 
new request before flush, that might destroy merging opportunities. I'll 
unify the mq/sq parts.

-- 
Jens Axboe


[-- Attachment #2: blk-mq-preempt-plug-flush.patch --]
[-- Type: text/x-patch, Size: 676 bytes --]

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 3ae09de62f19..0325dcec8c74 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1380,12 +1391,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
 		blk_mq_bio_to_request(rq, bio);
 		if (!request_count)
 			trace_block_plug(q);
-		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
+
+		list_add_tail(&rq->queuelist, &plug->mq_list);
+		blk_mq_put_ctx(data.ctx);
+
+		if (request_count + 1 >= BLK_MAX_REQUEST_COUNT) {
 			blk_flush_plug_list(plug, false);
 			trace_block_plug(q);
 		}
-		list_add_tail(&rq->queuelist, &plug->mq_list);
-		blk_mq_put_ctx(data.ctx);
+
 		return cookie;
 	}
 


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 21:30   ` Jens Axboe
@ 2015-11-20 23:08     ` Liu Bo
  2015-11-21  2:26       ` Jens Axboe
  0 siblings, 1 reply; 11+ messages in thread
From: Liu Bo @ 2015-11-20 23:08 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Chris Mason, linux-btrfs

On Fri, Nov 20, 2015 at 02:30:43PM -0700, Jens Axboe wrote:
> On 11/20/2015 06:13 AM, Chris Mason wrote:
> >On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> >>while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> >>so those sub-stripe writes are gatherred into plug callback list and
> >>hopefully we can have a full stripe writes.
> >>
> >>However, while processing these plugged callbacks, it's within an atomic
> >>context which is provided by blk_sq_make_request() because of a get_cpu()
> >>in blk_mq_get_ctx().
> >>
> >>This changes to always use btrfs_rmw_helper to complete the pending writes.
> >>
> >
> >Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
> >
> >Jens?
> 
> Yeah, blk-mq does have preemption disabled when it flushes, for the single
> queue setup. That's a bug. Attached is an untested patch that should fix it,
> can you try it?
> 

Although it runs into a warning one time of 50 tries, that was not atomic warning but another racy issue.

WARNING: CPU: 2 PID: 8531 at fs/btrfs/ctree.c:1162 __btrfs_cow_block+0x431/0x610 [btrfs]()

So overall the patch is good.

> I'll rework this to be a proper patch, not convinced we want to add the new
> request before flush, that might destroy merging opportunities. I'll unify
> the mq/sq parts.

That's true, xfstests didn't notice any performance difference but that cannot prove anything.

I'll test the new patch when you send it out.

Thanks,

-liubo

> 
> -- 
> Jens Axboe
> 

> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index 3ae09de62f19..0325dcec8c74 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -1380,12 +1391,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
>  		blk_mq_bio_to_request(rq, bio);
>  		if (!request_count)
>  			trace_block_plug(q);
> -		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
> +
> +		list_add_tail(&rq->queuelist, &plug->mq_list);
> +		blk_mq_put_ctx(data.ctx);
> +
> +		if (request_count + 1 >= BLK_MAX_REQUEST_COUNT) {
>  			blk_flush_plug_list(plug, false);
>  			trace_block_plug(q);
>  		}
> -		list_add_tail(&rq->queuelist, &plug->mq_list);
> -		blk_mq_put_ctx(data.ctx);
> +
>  		return cookie;
>  	}
>  
> 


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-20 23:08     ` Liu Bo
@ 2015-11-21  2:26       ` Jens Axboe
  2015-11-21  3:14         ` Liu Bo
  0 siblings, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2015-11-21  2:26 UTC (permalink / raw)
  To: bo.li.liu; +Cc: Chris Mason, linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 1645 bytes --]

On 11/20/2015 04:08 PM, Liu Bo wrote:
> On Fri, Nov 20, 2015 at 02:30:43PM -0700, Jens Axboe wrote:
>> On 11/20/2015 06:13 AM, Chris Mason wrote:
>>> On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
>>>> while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
>>>> so those sub-stripe writes are gatherred into plug callback list and
>>>> hopefully we can have a full stripe writes.
>>>>
>>>> However, while processing these plugged callbacks, it's within an atomic
>>>> context which is provided by blk_sq_make_request() because of a get_cpu()
>>>> in blk_mq_get_ctx().
>>>>
>>>> This changes to always use btrfs_rmw_helper to complete the pending writes.
>>>>
>>>
>>> Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
>>>
>>> Jens?
>>
>> Yeah, blk-mq does have preemption disabled when it flushes, for the single
>> queue setup. That's a bug. Attached is an untested patch that should fix it,
>> can you try it?
>>
>
> Although it runs into a warning one time of 50 tries, that was not atomic warning but another racy issue.
>
> WARNING: CPU: 2 PID: 8531 at fs/btrfs/ctree.c:1162 __btrfs_cow_block+0x431/0x610 [btrfs]()
>
> So overall the patch is good.
>
>> I'll rework this to be a proper patch, not convinced we want to add the new
>> request before flush, that might destroy merging opportunities. I'll unify
>> the mq/sq parts.
>
> That's true, xfstests didn't notice any performance difference but that cannot prove anything.
>
> I'll test the new patch when you send it out.

Try this one, that should retain the plug issue characteristics we care 
about as well.

-- 
Jens Axboe


[-- Attachment #2: blk-mq-preempt-plug-flush-v2.patch --]
[-- Type: text/x-patch, Size: 4156 bytes --]

diff --git a/block/blk-core.c b/block/blk-core.c
index 5131993b23a1..4237facaafa5 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -3192,7 +3192,7 @@ static void queue_unplugged(struct request_queue *q, unsigned int depth,
 	spin_unlock(q->queue_lock);
 }
 
-static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
+void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
 {
 	LIST_HEAD(callbacks);
 
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 3ae09de62f19..e92f52462222 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1065,7 +1065,8 @@ static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
 		  blk_rq_pos(rqa) < blk_rq_pos(rqb)));
 }
 
-void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
+static void __blk_mq_flush_plug_list(struct blk_plug *plug, bool from_sched,
+				     bool skip_last)
 {
 	struct blk_mq_ctx *this_ctx;
 	struct request_queue *this_q;
@@ -1084,13 +1085,15 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 
 	while (!list_empty(&list)) {
 		rq = list_entry_rq(list.next);
+		if (skip_last && list_is_last(&rq->queuelist, &list))
+			break;
 		list_del_init(&rq->queuelist);
 		BUG_ON(!rq->q);
 		if (rq->mq_ctx != this_ctx) {
 			if (this_ctx) {
 				blk_mq_insert_requests(this_q, this_ctx,
 							&ctx_list, depth,
-							from_schedule);
+							from_sched);
 			}
 
 			this_ctx = rq->mq_ctx;
@@ -1108,8 +1111,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 	 */
 	if (this_ctx) {
 		blk_mq_insert_requests(this_q, this_ctx, &ctx_list, depth,
-				       from_schedule);
+				       from_sched);
 	}
+
+}
+
+void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
+{
+	__blk_mq_flush_plug_list(plug, from_schedule, false);
 }
 
 static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
@@ -1291,15 +1300,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 		blk_mq_bio_to_request(rq, bio);
 
 		/*
-		 * we do limited pluging. If bio can be merged, do merge.
+		 * We do limited pluging. If the bio can be merged, do that.
 		 * Otherwise the existing request in the plug list will be
 		 * issued. So the plug list will have one request at most
 		 */
 		if (plug) {
 			/*
 			 * The plug list might get flushed before this. If that
-			 * happens, same_queue_rq is invalid and plug list is empty
-			 **/
+			 * happens, same_queue_rq is invalid and plug list is
+			 * empty
+			 */
 			if (same_queue_rq && !list_empty(&plug->mq_list)) {
 				old_rq = same_queue_rq;
 				list_del_init(&old_rq->queuelist);
@@ -1380,12 +1390,24 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
 		blk_mq_bio_to_request(rq, bio);
 		if (!request_count)
 			trace_block_plug(q);
-		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
-			blk_flush_plug_list(plug, false);
-			trace_block_plug(q);
-		}
+
 		list_add_tail(&rq->queuelist, &plug->mq_list);
 		blk_mq_put_ctx(data.ctx);
+
+		/*
+		 * We unplug manually here, flushing both callbacks and
+		 * potentially queued up IO - except the one we just added.
+		 * That one did not merge with existing requests, so could
+		 * be a candidate for new incoming merges. Tell
+		 * __blk_mq_flush_plug_list() to skip issuing the last
+		 * request in the list, which is the 'rq' from above.
+		 */
+		if (request_count >= BLK_MAX_REQUEST_COUNT) {
+			flush_plug_callbacks(plug, false);
+			__blk_mq_flush_plug_list(plug, false, true);
+			trace_block_plug(q);
+		}
+
 		return cookie;
 	}
 
diff --git a/block/blk.h b/block/blk.h
index c43926d3d74d..3e0ae1562b85 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -107,6 +107,7 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
 			    unsigned int *request_count,
 			    struct request **same_queue_rq);
 unsigned int blk_plug_queued_count(struct request_queue *q);
+void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule);
 
 void blk_account_io_start(struct request *req, bool new_io);
 void blk_account_io_completion(struct request *req, unsigned int bytes);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-21  2:26       ` Jens Axboe
@ 2015-11-21  3:14         ` Liu Bo
  2015-11-21  3:29           ` Jens Axboe
  0 siblings, 1 reply; 11+ messages in thread
From: Liu Bo @ 2015-11-21  3:14 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Chris Mason, linux-btrfs

On Fri, Nov 20, 2015 at 07:26:45PM -0700, Jens Axboe wrote:
> On 11/20/2015 04:08 PM, Liu Bo wrote:
> >On Fri, Nov 20, 2015 at 02:30:43PM -0700, Jens Axboe wrote:
> >>On 11/20/2015 06:13 AM, Chris Mason wrote:
> >>>On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> >>>>while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> >>>>so those sub-stripe writes are gatherred into plug callback list and
> >>>>hopefully we can have a full stripe writes.
> >>>>
> >>>>However, while processing these plugged callbacks, it's within an atomic
> >>>>context which is provided by blk_sq_make_request() because of a get_cpu()
> >>>>in blk_mq_get_ctx().
> >>>>
> >>>>This changes to always use btrfs_rmw_helper to complete the pending writes.
> >>>>
> >>>
> >>>Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
> >>>
> >>>Jens?
> >>
> >>Yeah, blk-mq does have preemption disabled when it flushes, for the single
> >>queue setup. That's a bug. Attached is an untested patch that should fix it,
> >>can you try it?
> >>
> >
> >Although it runs into a warning one time of 50 tries, that was not atomic warning but another racy issue.
> >
> >WARNING: CPU: 2 PID: 8531 at fs/btrfs/ctree.c:1162 __btrfs_cow_block+0x431/0x610 [btrfs]()
> >
> >So overall the patch is good.
> >
> >>I'll rework this to be a proper patch, not convinced we want to add the new
> >>request before flush, that might destroy merging opportunities. I'll unify
> >>the mq/sq parts.
> >
> >That's true, xfstests didn't notice any performance difference but that cannot prove anything.
> >
> >I'll test the new patch when you send it out.
> 
> Try this one, that should retain the plug issue characteristics we care
> about as well.

The test does not complain any more, thank for the quick patch.

Tested-by: Liu Bo <bo.li.liu@oracle.com>

Thanks,

-liubo
> 
> -- 
> Jens Axboe
> 

> diff --git a/block/blk-core.c b/block/blk-core.c
> index 5131993b23a1..4237facaafa5 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -3192,7 +3192,7 @@ static void queue_unplugged(struct request_queue *q, unsigned int depth,
>  	spin_unlock(q->queue_lock);
>  }
>  
> -static void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
> +void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule)
>  {
>  	LIST_HEAD(callbacks);
>  
> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index 3ae09de62f19..e92f52462222 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -1065,7 +1065,8 @@ static int plug_ctx_cmp(void *priv, struct list_head *a, struct list_head *b)
>  		  blk_rq_pos(rqa) < blk_rq_pos(rqb)));
>  }
>  
> -void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
> +static void __blk_mq_flush_plug_list(struct blk_plug *plug, bool from_sched,
> +				     bool skip_last)
>  {
>  	struct blk_mq_ctx *this_ctx;
>  	struct request_queue *this_q;
> @@ -1084,13 +1085,15 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
>  
>  	while (!list_empty(&list)) {
>  		rq = list_entry_rq(list.next);
> +		if (skip_last && list_is_last(&rq->queuelist, &list))
> +			break;
>  		list_del_init(&rq->queuelist);
>  		BUG_ON(!rq->q);
>  		if (rq->mq_ctx != this_ctx) {
>  			if (this_ctx) {
>  				blk_mq_insert_requests(this_q, this_ctx,
>  							&ctx_list, depth,
> -							from_schedule);
> +							from_sched);
>  			}
>  
>  			this_ctx = rq->mq_ctx;
> @@ -1108,8 +1111,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
>  	 */
>  	if (this_ctx) {
>  		blk_mq_insert_requests(this_q, this_ctx, &ctx_list, depth,
> -				       from_schedule);
> +				       from_sched);
>  	}
> +
> +}
> +
> +void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
> +{
> +	__blk_mq_flush_plug_list(plug, from_schedule, false);
>  }
>  
>  static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
> @@ -1291,15 +1300,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
>  		blk_mq_bio_to_request(rq, bio);
>  
>  		/*
> -		 * we do limited pluging. If bio can be merged, do merge.
> +		 * We do limited pluging. If the bio can be merged, do that.
>  		 * Otherwise the existing request in the plug list will be
>  		 * issued. So the plug list will have one request at most
>  		 */
>  		if (plug) {
>  			/*
>  			 * The plug list might get flushed before this. If that
> -			 * happens, same_queue_rq is invalid and plug list is empty
> -			 **/
> +			 * happens, same_queue_rq is invalid and plug list is
> +			 * empty
> +			 */
>  			if (same_queue_rq && !list_empty(&plug->mq_list)) {
>  				old_rq = same_queue_rq;
>  				list_del_init(&old_rq->queuelist);
> @@ -1380,12 +1390,24 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
>  		blk_mq_bio_to_request(rq, bio);
>  		if (!request_count)
>  			trace_block_plug(q);
> -		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
> -			blk_flush_plug_list(plug, false);
> -			trace_block_plug(q);
> -		}
> +
>  		list_add_tail(&rq->queuelist, &plug->mq_list);
>  		blk_mq_put_ctx(data.ctx);
> +
> +		/*
> +		 * We unplug manually here, flushing both callbacks and
> +		 * potentially queued up IO - except the one we just added.
> +		 * That one did not merge with existing requests, so could
> +		 * be a candidate for new incoming merges. Tell
> +		 * __blk_mq_flush_plug_list() to skip issuing the last
> +		 * request in the list, which is the 'rq' from above.
> +		 */
> +		if (request_count >= BLK_MAX_REQUEST_COUNT) {
> +			flush_plug_callbacks(plug, false);
> +			__blk_mq_flush_plug_list(plug, false, true);
> +			trace_block_plug(q);
> +		}
> +
>  		return cookie;
>  	}
>  
> diff --git a/block/blk.h b/block/blk.h
> index c43926d3d74d..3e0ae1562b85 100644
> --- a/block/blk.h
> +++ b/block/blk.h
> @@ -107,6 +107,7 @@ bool blk_attempt_plug_merge(struct request_queue *q, struct bio *bio,
>  			    unsigned int *request_count,
>  			    struct request **same_queue_rq);
>  unsigned int blk_plug_queued_count(struct request_queue *q);
> +void flush_plug_callbacks(struct blk_plug *plug, bool from_schedule);
>  
>  void blk_account_io_start(struct request *req, bool new_io);
>  void blk_account_io_completion(struct request *req, unsigned int bytes);


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-21  3:14         ` Liu Bo
@ 2015-11-21  3:29           ` Jens Axboe
  2015-11-21  6:05             ` Liu Bo
  0 siblings, 1 reply; 11+ messages in thread
From: Jens Axboe @ 2015-11-21  3:29 UTC (permalink / raw)
  To: bo.li.liu; +Cc: Chris Mason, linux-btrfs

[-- Attachment #1: Type: text/plain, Size: 2113 bytes --]

On 11/20/2015 08:14 PM, Liu Bo wrote:
> On Fri, Nov 20, 2015 at 07:26:45PM -0700, Jens Axboe wrote:
>> On 11/20/2015 04:08 PM, Liu Bo wrote:
>>> On Fri, Nov 20, 2015 at 02:30:43PM -0700, Jens Axboe wrote:
>>>> On 11/20/2015 06:13 AM, Chris Mason wrote:
>>>>> On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
>>>>>> while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
>>>>>> so those sub-stripe writes are gatherred into plug callback list and
>>>>>> hopefully we can have a full stripe writes.
>>>>>>
>>>>>> However, while processing these plugged callbacks, it's within an atomic
>>>>>> context which is provided by blk_sq_make_request() because of a get_cpu()
>>>>>> in blk_mq_get_ctx().
>>>>>>
>>>>>> This changes to always use btrfs_rmw_helper to complete the pending writes.
>>>>>>
>>>>>
>>>>> Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
>>>>>
>>>>> Jens?
>>>>
>>>> Yeah, blk-mq does have preemption disabled when it flushes, for the single
>>>> queue setup. That's a bug. Attached is an untested patch that should fix it,
>>>> can you try it?
>>>>
>>>
>>> Although it runs into a warning one time of 50 tries, that was not atomic warning but another racy issue.
>>>
>>> WARNING: CPU: 2 PID: 8531 at fs/btrfs/ctree.c:1162 __btrfs_cow_block+0x431/0x610 [btrfs]()
>>>
>>> So overall the patch is good.
>>>
>>>> I'll rework this to be a proper patch, not convinced we want to add the new
>>>> request before flush, that might destroy merging opportunities. I'll unify
>>>> the mq/sq parts.
>>>
>>> That's true, xfstests didn't notice any performance difference but that cannot prove anything.
>>>
>>> I'll test the new patch when you send it out.
>>
>> Try this one, that should retain the plug issue characteristics we care
>> about as well.
>
> The test does not complain any more, thank for the quick patch.
>
> Tested-by: Liu Bo <bo.li.liu@oracle.com>

Can I talk you into trying this one? It's simpler, does the same thing. 
We don't need to overcomplicate it, it's fine not having preempt 
disabled for adding to the list.

-- 
Jens Axboe


[-- Attachment #2: blk-mq-preempt-plug-flush-v3.patch --]
[-- Type: text/x-patch, Size: 1380 bytes --]

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 3ae09de62f19..6d6f8feb48c0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -1291,15 +1291,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 		blk_mq_bio_to_request(rq, bio);
 
 		/*
-		 * we do limited pluging. If bio can be merged, do merge.
+		 * We do limited pluging. If the bio can be merged, do that.
 		 * Otherwise the existing request in the plug list will be
 		 * issued. So the plug list will have one request at most
 		 */
 		if (plug) {
 			/*
 			 * The plug list might get flushed before this. If that
-			 * happens, same_queue_rq is invalid and plug list is empty
-			 **/
+			 * happens, same_queue_rq is invalid and plug list is
+			 * empty
+			 */
 			if (same_queue_rq && !list_empty(&plug->mq_list)) {
 				old_rq = same_queue_rq;
 				list_del_init(&old_rq->queuelist);
@@ -1380,12 +1381,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
 		blk_mq_bio_to_request(rq, bio);
 		if (!request_count)
 			trace_block_plug(q);
-		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
+
+		blk_mq_put_ctx(data.ctx);
+
+		if (request_count >= BLK_MAX_REQUEST_COUNT) {
 			blk_flush_plug_list(plug, false);
 			trace_block_plug(q);
 		}
+
 		list_add_tail(&rq->queuelist, &plug->mq_list);
-		blk_mq_put_ctx(data.ctx);
 		return cookie;
 	}
 

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] Btrfs: fix a bug of sleeping in atomic context
  2015-11-21  3:29           ` Jens Axboe
@ 2015-11-21  6:05             ` Liu Bo
  0 siblings, 0 replies; 11+ messages in thread
From: Liu Bo @ 2015-11-21  6:05 UTC (permalink / raw)
  To: Jens Axboe; +Cc: Chris Mason, linux-btrfs

On Fri, Nov 20, 2015 at 08:29:06PM -0700, Jens Axboe wrote:
> On 11/20/2015 08:14 PM, Liu Bo wrote:
> >On Fri, Nov 20, 2015 at 07:26:45PM -0700, Jens Axboe wrote:
> >>On 11/20/2015 04:08 PM, Liu Bo wrote:
> >>>On Fri, Nov 20, 2015 at 02:30:43PM -0700, Jens Axboe wrote:
> >>>>On 11/20/2015 06:13 AM, Chris Mason wrote:
> >>>>>On Thu, Nov 19, 2015 at 05:49:37PM -0800, Liu Bo wrote:
> >>>>>>while xfstesting, this bug[1] is spotted by both btrfs/061 and btrfs/063,
> >>>>>>so those sub-stripe writes are gatherred into plug callback list and
> >>>>>>hopefully we can have a full stripe writes.
> >>>>>>
> >>>>>>However, while processing these plugged callbacks, it's within an atomic
> >>>>>>context which is provided by blk_sq_make_request() because of a get_cpu()
> >>>>>>in blk_mq_get_ctx().
> >>>>>>
> >>>>>>This changes to always use btrfs_rmw_helper to complete the pending writes.
> >>>>>>
> >>>>>
> >>>>>Thanks Liu, but MD raid has the same troubles, we're not atomic in our unplugs.
> >>>>>
> >>>>>Jens?
> >>>>
> >>>>Yeah, blk-mq does have preemption disabled when it flushes, for the single
> >>>>queue setup. That's a bug. Attached is an untested patch that should fix it,
> >>>>can you try it?
> >>>>
> >>>
> >>>Although it runs into a warning one time of 50 tries, that was not atomic warning but another racy issue.
> >>>
> >>>WARNING: CPU: 2 PID: 8531 at fs/btrfs/ctree.c:1162 __btrfs_cow_block+0x431/0x610 [btrfs]()
> >>>
> >>>So overall the patch is good.
> >>>
> >>>>I'll rework this to be a proper patch, not convinced we want to add the new
> >>>>request before flush, that might destroy merging opportunities. I'll unify
> >>>>the mq/sq parts.
> >>>
> >>>That's true, xfstests didn't notice any performance difference but that cannot prove anything.
> >>>
> >>>I'll test the new patch when you send it out.
> >>
> >>Try this one, that should retain the plug issue characteristics we care
> >>about as well.
> >
> >The test does not complain any more, thank for the quick patch.
> >
> >Tested-by: Liu Bo <bo.li.liu@oracle.com>
> 
> Can I talk you into trying this one? It's simpler, does the same thing. We
> don't need to overcomplicate it, it's fine not having preempt disabled for
> adding to the list.

Of course, I've run the case with the patch for 20 times, no more
warnings, thanks for the fix.

Thanks,

-liubo

> 
> -- 
> Jens Axboe
> 

> diff --git a/block/blk-mq.c b/block/blk-mq.c
> index 3ae09de62f19..6d6f8feb48c0 100644
> --- a/block/blk-mq.c
> +++ b/block/blk-mq.c
> @@ -1291,15 +1291,16 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
>  		blk_mq_bio_to_request(rq, bio);
>  
>  		/*
> -		 * we do limited pluging. If bio can be merged, do merge.
> +		 * We do limited pluging. If the bio can be merged, do that.
>  		 * Otherwise the existing request in the plug list will be
>  		 * issued. So the plug list will have one request at most
>  		 */
>  		if (plug) {
>  			/*
>  			 * The plug list might get flushed before this. If that
> -			 * happens, same_queue_rq is invalid and plug list is empty
> -			 **/
> +			 * happens, same_queue_rq is invalid and plug list is
> +			 * empty
> +			 */
>  			if (same_queue_rq && !list_empty(&plug->mq_list)) {
>  				old_rq = same_queue_rq;
>  				list_del_init(&old_rq->queuelist);
> @@ -1380,12 +1381,15 @@ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio)
>  		blk_mq_bio_to_request(rq, bio);
>  		if (!request_count)
>  			trace_block_plug(q);
> -		else if (request_count >= BLK_MAX_REQUEST_COUNT) {
> +
> +		blk_mq_put_ctx(data.ctx);
> +
> +		if (request_count >= BLK_MAX_REQUEST_COUNT) {
>  			blk_flush_plug_list(plug, false);
>  			trace_block_plug(q);
>  		}
> +
>  		list_add_tail(&rq->queuelist, &plug->mq_list);
> -		blk_mq_put_ctx(data.ctx);
>  		return cookie;
>  	}
>  


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-11-21  6:05 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-20  1:49 [PATCH] Btrfs: fix a bug of sleeping in atomic context Liu Bo
2015-11-20 13:13 ` Chris Mason
2015-11-20 17:57   ` Liu Bo
2015-11-20 20:06     ` Liu Bo
2015-11-20 20:09       ` Chris Mason
2015-11-20 21:30   ` Jens Axboe
2015-11-20 23:08     ` Liu Bo
2015-11-21  2:26       ` Jens Axboe
2015-11-21  3:14         ` Liu Bo
2015-11-21  3:29           ` Jens Axboe
2015-11-21  6:05             ` Liu Bo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.