Re: [PATCH] block: fix possible race on blk_get_queue()

From: Bart Van Assche
Date: Tue Jul 28 2020 - 22:41:54 EST


On 2020-07-28 18:51, Luis Chamberlain wrote:
> diff --git a/block/blk-core.c b/block/blk-core.c
> index d9d632639bd1..febdd8e8d409 100644
> --- a/block/blk-core.c
> +++ b/block/blk-core.c
> @@ -605,12 +605,18 @@ EXPORT_SYMBOL(blk_alloc_queue);
> */
> bool blk_get_queue(struct request_queue *q)
> {
> - if (likely(!blk_queue_dying(q))) {
> - __blk_get_queue(q);
> - return true;
> + struct kobject *obj;
> +
> + obj = __blk_get_queue(q);
> + if (!obj)
> + return false;
> +
> + if (unlikely(blk_queue_dying(q))) {
> + blk_put_queue(q);
> + return false;
> }
>
> - return false;
> + return true;
> }

This change is not sufficient to prevent that the QUEUE_FLAG_DYING flag
is set immediately after this function returns. I propose not to modify
this function but instead to add a comment that is the responsibility of
the caller to prevent that such a race condition occurs.

> -static inline void __blk_get_queue(struct request_queue *q)
> +static inline struct kobject * __must_check
> +__blk_get_queue(struct request_queue *q)
> {
> - kobject_get(&q->kobj);
> + return kobject_get_unless_zero(&q->kobj);
> }

If a function passes a queue pointer to another function that calls
blk_get_queue() then the caller should guarantee that 'q' is valid
during the entire duration of the call. In other words, I'm not sure the
above change is an improvement.

Thanks,

Bart.