Hi Sandeep, On 2023/6/21 04:38, Sandeep Dhavale wrote:
Hi, I think we are under RCU read lock in the stack at blk_mq_flush_plug_list+0x2b0/0x354blk_mq_flush_plug_list calls blk_mq_run_dispatch_ops which is a macro in block/blk-mq.h /* run the code block in @dispatch_ops with rcu/srcu read lock held */ #define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \ do { \ if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \ struct blk_mq_tag_set *__tag_set = (q)->tag_set; \ int srcu_idx; \ \ might_sleep_if(check_sleep); \ srcu_idx = srcu_read_lock(__tag_set->srcu); \ (dispatch_ops); \ srcu_read_unlock(__tag_set->srcu, srcu_idx); \ } else { \ rcu_read_lock(); \ (dispatch_ops); \ rcu_read_unlock(); \ } \ } while (0) #define blk_mq_run_dispatch_ops(q, dispatch_ops) \ __blk_mq_run_dispatch_ops(q, true, dispatch_ops) \ As you can see if BLK_MQ_F_BLOCKING is not set then dispatch_ops is called with rcu_read_lock(). rcu_read_lock() __rcu_read_lock() rcu_preempt_read_enter() In rcu_preempt_read_enter() increments the rcu_read_lock_nesting which is detected later during mutex_lock() as a warning.
Thanks for your analysis. That is much helpful to me. So it seems a new path which calls end_io under rcu read lock.
Regarding use of !in_task(), that cannot detect rcu_read_lock_nesting as far as I can tell so that may not be sufficient.
rcu_preempt_depth is a too low level api, I'm not sure if it's a good way but we really don't want to trigger another workqueue here, could we just use: "!in_task() || irqs_disabled() || rcu_read_lock_any_held()" Or do you have better ideas? Thanks, Gao Xiang
Thanks, Sandeep.
