diff mbox series

[2/3] blk-core: introduce queue close feature

Message ID 1536120586-3378-3-git-send-email-jianchao.w.wang@oracle.com (mailing list archive)
State New, archived
Headers show
Series Introduce a light-weight queue close feature | expand

Commit Message

jianchao.wang Sept. 5, 2018, 4:09 a.m. UTC
blk queue freeze is often used to prevent new IO from entering
request queue. However, becuase we kill the percpu-ref
q_usage_counter when freeze queue, we have to drain the request
queue when unfreeze. This is unnecessary for just preventing new
IO. In addition, If there is IO timeout or other issue when unfreeze
the queue, the scenario could be very tricky.

So we introduce BLK_QUEUE_GATE_CLOSED to implement a light-weight
queue close feature base on the queue_gate to prevent new IO from
comming in queue which will not need to drain the queue any more.

Signed-off-by: Jianchao Wang <jianchao.w.wang@oracle.com>
---
 block/blk-core.c       | 17 +++++++++++++++++
 block/blk.h            |  1 +
 include/linux/blkdev.h |  3 +++
 3 files changed, 21 insertions(+)

Comments

Bart Van Assche Sept. 5, 2018, 3:57 p.m. UTC | #1
On Wed, 2018-09-05 at 12:09 +0800, Jianchao Wang wrote:
> blk queue freeze is often used to prevent new IO from entering
> request queue. However, becuase we kill the percpu-ref
> q_usage_counter when freeze queue, we have to drain the request
> queue when unfreeze. This is unnecessary for just preventing new
> IO. In addition, If there is IO timeout or other issue when unfreeze
> the queue, the scenario could be very tricky.
> 
> So we introduce BLK_QUEUE_GATE_CLOSED to implement a light-weight
> queue close feature base on the queue_gate to prevent new IO from
> comming in queue which will not need to drain the queue any more.

Does the "queue gate close" feature cause blk_get_request() /
blk_mq_get_request() to block until blk_clear_queue_closed() is called? If
so, I think we need a better name for this feature. How about calling these
two operations suspend and resume?

Thanks,

Bart.
jianchao.wang Sept. 6, 2018, 1:31 a.m. UTC | #2
Hi Bart

On 09/05/2018 11:57 PM, Bart Van Assche wrote:
> On Wed, 2018-09-05 at 12:09 +0800, Jianchao Wang wrote:
>> blk queue freeze is often used to prevent new IO from entering
>> request queue. However, becuase we kill the percpu-ref
>> q_usage_counter when freeze queue, we have to drain the request
>> queue when unfreeze. This is unnecessary for just preventing new
>> IO. In addition, If there is IO timeout or other issue when unfreeze
>> the queue, the scenario could be very tricky.
>>
>> So we introduce BLK_QUEUE_GATE_CLOSED to implement a light-weight
>> queue close feature base on the queue_gate to prevent new IO from
>> comming in queue which will not need to drain the queue any more.
> 
> Does the "queue gate close" feature cause blk_get_request() /
> blk_mq_get_request() to block until blk_clear_queue_closed() is called? 

Yes. It works in blk_queue_enter. So it could cover blk_mq_get_request

If
> so, I think we need a better name for this feature. How about calling these
> two operations suspend and resume?

I'm open for it. :)

> 
> Thanks,
> 
> Bart.
>
diff mbox series

Patch

diff --git a/block/blk-core.c b/block/blk-core.c
index d1bdded..b073c68 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -449,6 +449,23 @@  void blk_clear_preempt_only(struct request_queue *q)
 }
 EXPORT_SYMBOL_GPL(blk_clear_preempt_only);
 
+int blk_set_queue_closed(struct request_queue *q)
+{
+	if (test_and_set_bit(BLK_QUEUE_GATE_CLOSED, &q->queue_gate))
+		return 1;
+
+	synchronize_rcu();
+	return 0;
+}
+EXPORT_SYMBOL_GPL(blk_set_queue_closed);
+
+void blk_clear_queue_closed(struct request_queue *q)
+{
+	clear_bit(BLK_QUEUE_GATE_CLOSED, &q->queue_gate);
+	wake_up_all(&q->mq_freeze_wq);
+}
+EXPORT_SYMBOL_GPL(blk_clear_queue_closed);
+
 /**
  * __blk_run_queue_uncond - run a queue whether or not it has been stopped
  * @q:	The queue to run
diff --git a/block/blk.h b/block/blk.h
index cdef4c1..90ff6bb 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -21,6 +21,7 @@  extern struct dentry *blk_debugfs_root;
 
 enum blk_queue_gate_flag_t {
 	BLK_QUEUE_GATE_PREEMPT_ONLY,
+	BLK_QUEUE_GATE_CLOSED,
 };
 
 struct blk_flush_queue {
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 4a33814..a7f77da 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -741,6 +741,9 @@  bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q);
 extern int blk_set_preempt_only(struct request_queue *q);
 extern void blk_clear_preempt_only(struct request_queue *q);
 
+extern int blk_set_queue_closed(struct request_queue *q);
+extern void blk_clear_queue_closed(struct request_queue *q);
+
 static inline int queue_in_flight(struct request_queue *q)
 {
 	return q->in_flight[0] + q->in_flight[1];