Hello, Tejun.

在 2026/9/30 00:27, Tejun Heo 写道:
> Hello, Tao.
> 
> On Tue, 29 Sep 2026 21:42:51 +0800, Tao Cui wrote:
>> That leaves one race: .unreg may observe a non-NULL ops->q before
>> ioc_rqos_exit() clears it, then block on rq_qos_mutex while the
>> ejection drops the last bdev reference.  This looks analogous to
>> hid_bpf's .unreg vs. destroy_device synchronization.
>>
>> Does that seem acceptable here too, or would you rather have .unreg
>> own the final reference unconditionally?
> 
> No, there can't be a crash window like that. The underlying problem is
> that .unreg sleeps on a mutex inside a queue it holds no reference on. The
> model should still be ejected when the device goes away, but exactly when
> doesn't matter much as long as it happens in a reasonable amount of time.
> 
> request_queues are RCU-freed, so maybe .unreg can rcu_dereference() ops->q
> and try to get a queue reference under rcu_read_lock()? blk_get_queue()
> fails on a dying queue, so this would need a tryget wrapper around
> q->refs. Holding its own reference, .unreg can then take rq_qos_mutex and
> test ops->q for NULL to tell whether removal already ejected the model.
> 

.unreg now takes a queue reference before entering the queue: it
rcu_dereferences ops->q under rcu_read_lock() and uses a queue
reference tryget helper to keep the queue valid across the mutex wait.  With
the reference held, .unreg freezes and quiesces the queue, takes
rq_qos_mutex and re-checks ops->q for NULL, so it can handle both the
normal detach path and the case where removal has already ejected
the model.
> Also, when .unreg detaches, the device is still live and the BPF code may
> be running. Freezing and quiescing the queue covers the IO paths but not
> iocg_init() and iocg_free() called from ioc_pd_init() and ioc_pd_free(),
> so the iocg_free() walk and clearing the model need to be synchronized
> against those too.
> 

Clearing the model and the iocg_free() walk are now synchronized
under q->blkcg_mutex.  This is the same mutex used when
blkg_create() and blkg_free_workfn() invoke pd_init_fn() and
pd_free_fn(), so the detach path is synchronized with the normal pd
callback paths.

While reworking the attach path, I also fixed two related issues I
noticed: the attach path no longer uses the ioc after releasing
rq_qos_mutex, and blkdev_get_no_open() failures are handled
correctly for unknown dev_t values.

v8 will follow shortly.

Thanks.
Tao

> Thanks.
> 
> --
> tejun


Reply via email to