From 3ef28e83ab15799742e55fd13243a5f678b04242 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 21 Oct 2015 13:20:12 -0400 Subject: block: generic request_queue reference counting Allow pmem, and other synchronous/bio-based block drivers, to fallback on a per-cpu reference count managed by the core for tracking queue live/dead state. The existing per-cpu reference count for the blk_mq case is promoted to be used in all block i/o scenarios. This involves initializing it by default, waiting for it to drop to zero at exit, and holding a live reference over the invocation of q->make_request_fn() in generic_make_request(). The blk_mq code continues to take its own reference per blk_mq request and retains the ability to freeze the queue, but the check that the queue is frozen is moved to generic_make_request(). This fixes crash signatures like the following: BUG: unable to handle kernel paging request at ffff880140000000 [..] Call Trace: [] ? copy_user_handle_tail+0x5f/0x70 [] pmem_do_bvec.isra.11+0x70/0xf0 [nd_pmem] [] pmem_make_request+0xd1/0x200 [nd_pmem] [] ? mempool_alloc+0x72/0x1a0 [] generic_make_request+0xd6/0x110 [] submit_bio+0x76/0x170 [] submit_bh_wbc+0x12f/0x160 [] submit_bh+0x12/0x20 [] jbd2_write_superblock+0x8d/0x170 [] jbd2_mark_journal_empty+0x5d/0x90 [] jbd2_journal_destroy+0x24b/0x270 [] ? put_pwq_unlocked+0x2a/0x30 [] ? destroy_workqueue+0x225/0x250 [] ext4_put_super+0x64/0x360 [] generic_shutdown_super+0x6a/0xf0 Cc: Jens Axboe Cc: Keith Busch Cc: Ross Zwisler Suggested-by: Christoph Hellwig Reviewed-by: Christoph Hellwig Tested-by: Ross Zwisler Signed-off-by: Dan Williams Signed-off-by: Jens Axboe --- block/blk.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'block/blk.h') diff --git a/block/blk.h b/block/blk.h index 98614ad37c81..5b2cd393afbe 100644 --- a/block/blk.h +++ b/block/blk.h @@ -72,6 +72,20 @@ void blk_dequeue_request(struct request *rq); void __blk_queue_free_tags(struct request_queue *q); bool __blk_end_bidi_request(struct request *rq, int error, unsigned int nr_bytes, unsigned int bidi_bytes); +int blk_queue_enter(struct request_queue *q, gfp_t gfp); +void blk_queue_exit(struct request_queue *q); +void blk_freeze_queue(struct request_queue *q); + +static inline void blk_queue_enter_live(struct request_queue *q) +{ + /* + * Given that running in generic_make_request() context + * guarantees that a live reference against q_usage_counter has + * been established, further references under that same context + * need not check that the queue has been frozen (marked dead). + */ + percpu_ref_get(&q->q_usage_counter); +} void blk_rq_timed_out_timer(unsigned long data); unsigned long blk_rq_timeout(unsigned long timeout); -- cgit v1.2.3 From 5a48fc147d7f2718a5c7e73bc8c4067235791fc1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 21 Oct 2015 13:20:23 -0400 Subject: block: blk_flush_integrity() for bio-based drivers Since they lack requests to pin the request_queue active, synchronous bio-based drivers may have in-flight integrity work from bio_integrity_endio() that is not flushed by blk_freeze_queue(). Flush that work to prevent races to free the queue and the final usage of the blk_integrity profile. This is temporary unless/until bio-based drivers start to generically take a q_usage_counter reference while a bio is in-flight. Cc: Martin K. Petersen [martin: fix the CONFIG_BLK_DEV_INTEGRITY=n case] Tested-by: Ross Zwisler Signed-off-by: Dan Williams Signed-off-by: Jens Axboe --- block/blk.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'block/blk.h') diff --git a/block/blk.h b/block/blk.h index 5b2cd393afbe..157c93d54dc9 100644 --- a/block/blk.h +++ b/block/blk.h @@ -87,6 +87,14 @@ static inline void blk_queue_enter_live(struct request_queue *q) percpu_ref_get(&q->q_usage_counter); } +#ifdef CONFIG_BLK_DEV_INTEGRITY +void blk_flush_integrity(void); +#else +static inline void blk_flush_integrity(void) +{ +} +#endif + void blk_rq_timed_out_timer(unsigned long data); unsigned long blk_rq_timeout(unsigned long timeout); void blk_add_timer(struct request *req); -- cgit v1.2.3