EROFS: Detecting atomic contexts

Gao Xiang hsiangkao at linux.alibaba.com
Wed Jun 21 10:38:29 AEST 2023


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/0x354
> 
> blk_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.


More information about the Linux-erofs mailing list