2022-10-29 10:25:31

by Jinlong Chen

[permalink] [raw]
Subject: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

Calling blk_freeze_queue results in a redundant call to
blk_freeze_queue_start as it has been called in blk_queue_start_drain.

Replace blk_freeze_queue with blk_mq_freeze_queue_wait to avoid the
redundant call.

Signed-off-by: Jinlong Chen <[email protected]>
---
block/blk-mq.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/block/blk-mq.c b/block/blk-mq.c
index 4cecf281123f..14c4165511b9 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -4005,7 +4005,12 @@ void blk_mq_destroy_queue(struct request_queue *q)

blk_queue_flag_set(QUEUE_FLAG_DYING, q);
blk_queue_start_drain(q);
- blk_freeze_queue(q);
+
+ /*
+ * blk_freeze_queue_start has been called in blk_queue_start_drain, we just
+ * need to wait.
+ */
+ blk_mq_freeze_queue_wait(q);

blk_sync_queue(q);
blk_mq_cancel_work_sync(q);
--
2.31.1



2022-10-30 00:37:12

by Bart Van Assche

[permalink] [raw]
Subject: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

On 10/29/22 03:02, Jinlong Chen wrote:
> Calling blk_freeze_queue results in a redundant call to
> blk_freeze_queue_start as it has been called in blk_queue_start_drain.
>
> Replace blk_freeze_queue with blk_mq_freeze_queue_wait to avoid the
> redundant call.

blk_mq_destroy_queue() has more callers than blk_queue_start_drain() so
the above description is at least misleading.

Additionally, the word "cleanup" from the patch series title indicates
that no patch in this series changes the behavior of the code. This
patch involves a behavior change.

I think this patch introduces a hang for every caller of
blk_mq_destroy_queue() other than blk_queue_start_drain().

Bart.

2022-10-30 03:10:49

by Jinlong Chen

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

Hi, Bart.

> > Calling blk_freeze_queue results in a redundant call to
> > blk_freeze_queue_start as it has been called in blk_queue_start_drain.
> >
> > Replace blk_freeze_queue with blk_mq_freeze_queue_wait to avoid the
> > redundant call.
>
> blk_mq_destroy_queue() has more callers than blk_queue_start_drain() so
> the above description is at least misleading.
>
> Additionally, the word "cleanup" from the patch series title indicates
> that no patch in this series changes the behavior of the code. This
> patch involves a behavior change.

Sorry for my poor description. I'll send a new series with these
description problems resolved.

> I think this patch introduces a hang for every caller of
> blk_mq_destroy_queue() other than blk_queue_start_drain().
>
> Bart.

I don't see why the patch introduces a hang. The calling relationship in
blk_mq_destroy_queue is as follows:

blk_mq_destroy_queue()
...
-> blk_queue_start_drain()
-> blk_freeze_queue_start() <- called
...
-> blk_freeze_queue()
-> blk_freeze_queue_start() <- called again
-> blk_mq_freeze_queue_wait()
...

So I think there is a redundant call to blk_freeze_queue_start(), we
just need to call blk_mq_freeze_queue_wait() after calling
blk_queue_start_drain().

Thanks!
Jinlong Chen

2022-10-30 15:06:41

by Bart Van Assche

[permalink] [raw]
Subject: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

On 10/29/22 19:27, Jinlong Chen wrote:
>> I think this patch introduces a hang for every caller of
>> blk_mq_destroy_queue() other than blk_queue_start_drain().
>> I don't see why the patch introduces a hang. The calling relationship in
> blk_mq_destroy_queue is as follows: [ ... ]

Agreed - what I wrote is wrong.

> So I think there is a redundant call to blk_freeze_queue_start(), we
> just need to call blk_mq_freeze_queue_wait() after calling
> blk_queue_start_drain().

I think it is on purpose that blk_queue_start_drain() freezes the
request queue and never unfreezes it. So if you want to change this
behavior it's up to you to motivate why you want to change this behavior
and also why it is safe to make that change. See also commit
d3cfb2a0ac0b ("block: block new I/O just after queue is set as dying").

Bart.


2022-10-30 15:33:08

by Jinlong Chen

[permalink] [raw]
Subject: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

> > So I think there is a redundant call to blk_freeze_queue_start(), we
> > just need to call blk_mq_freeze_queue_wait() after calling
> > blk_queue_start_drain().
>
> I think it is on purpose that blk_queue_start_drain() freezes the
> request queue and never unfreezes it. So if you want to change this
> behavior it's up to you to motivate why you want to change this behavior
> and also why it is safe to make that change. See also commit
> d3cfb2a0ac0b ("block: block new I/O just after queue is set as dying").
>
> Bart.

I think there might be some misunderstanding. I didn't touch
blk_queue_start_drain(), so its behavior is not changed. What I have done
is just replacing blk_freeze_queue() with blk_mq_freeze_queue_wait() in
blk_mq_destroy_queue().

See:
- https://lore.kernel.org/linux-block/[email protected]/T/#t

Thanks!
Jinlong Chen

2022-10-30 20:35:18

by Bart Van Assche

[permalink] [raw]
Subject: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

On 10/30/22 07:55, Jinlong Chen wrote:
>>> So I think there is a redundant call to blk_freeze_queue_start(), we
>>> just need to call blk_mq_freeze_queue_wait() after calling
>>> blk_queue_start_drain().
>>
>> I think it is on purpose that blk_queue_start_drain() freezes the
>> request queue and never unfreezes it. So if you want to change this
>> behavior it's up to you to motivate why you want to change this behavior
>> and also why it is safe to make that change. See also commit
>> d3cfb2a0ac0b ("block: block new I/O just after queue is set as dying").
>
> I think there might be some misunderstanding. I didn't touch
> blk_queue_start_drain(), so its behavior is not changed. What I have done
> is just replacing blk_freeze_queue() with blk_mq_freeze_queue_wait() in
> blk_mq_destroy_queue().

Hi Jinlong,

Does this mean that you want me to provide more information about what I
wrote? Without this patch, blk_mq_destroy_queue() uses two mechanisms to
block future I/O requests:
1. Set the flag QUEUE_FLAG_DYING.
2. Freeze the request queue and leave it frozen.

Your patch modifies blk_mq_destroy_queue() such that it unfreezes the
request queue after I/O has been quiesced instead of leaving it frozen.
I would appreciate it if Ming Lei (Cc-ed) could comment on this change
since I think that Ming introduced (2) in blk_mq_destroy_queue()
(formerly called blk_cleanup_queue()).

Thanks,

Bart.

2022-10-31 02:24:05

by Jinlong Chen

[permalink] [raw]
Subject: Re: Re: [PATCH 1/3] blk-mq: remove redundant call to blk_freeze_queue_start in blk_mq_destroy_queue

> On 10/30/22 07:55, Jinlong Chen wrote:
> >>> So I think there is a redundant call to blk_freeze_queue_start(), we
> >>> just need to call blk_mq_freeze_queue_wait() after calling
> >>> blk_queue_start_drain().
> >>
> >> I think it is on purpose that blk_queue_start_drain() freezes the
> >> request queue and never unfreezes it. So if you want to change this
> >> behavior it's up to you to motivate why you want to change this behavior
> >> and also why it is safe to make that change. See also commit
> >> d3cfb2a0ac0b ("block: block new I/O just after queue is set as dying").
> >
> > I think there might be some misunderstanding. I didn't touch
> > blk_queue_start_drain(), so its behavior is not changed. What I have done
> > is just replacing blk_freeze_queue() with blk_mq_freeze_queue_wait() in
> > blk_mq_destroy_queue().
>
> Hi Jinlong,
>
> Does this mean that you want me to provide more information about what I
> wrote? Without this patch, blk_mq_destroy_queue() uses two mechanisms to
> block future I/O requests:
> 1. Set the flag QUEUE_FLAG_DYING.
> 2. Freeze the request queue and leave it frozen.

I agreed.

> Your patch modifies blk_mq_destroy_queue() such that it unfreezes the
> request queue after I/O has been quiesced instead of leaving it frozen.

This is what blk_mq_destroy_queue() looks like with the patch (removed
the stupid comment as suggested by Christoph Hellwig):

void blk_mq_destroy_queue(struct request_queue *q)
{
WARN_ON_ONCE(!queue_is_mq(q));
WARN_ON_ONCE(blk_queue_registered(q));

might_sleep();

blk_queue_flag_set(QUEUE_FLAG_DYING, q);
blk_queue_start_drain(q);
blk_mq_freeze_queue_wait(q);

blk_sync_queue(q);
blk_mq_cancel_work_sync(q);
blk_mq_exit_queue(q);
}

I can't see where the unfreezing happens. Did I miss something?

> I would appreciate it if Ming Lei (Cc-ed) could comment on this change
> since I think that Ming introduced (2) in blk_mq_destroy_queue()
> (formerly called blk_cleanup_queue()).

I would appreciate it too.

Thanks!
Jinlong Chen