EROFS: Detecting atomic contexts

Sandeep Dhavale dhavale at google.com
Wed Jun 21 16:18:45 AEST 2023


On Tue, Jun 20, 2023 at 5:38 PM Gao Xiang <hsiangkao at linux.alibaba.com> wrote:
>
> 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()"
>
I think this looks good. rcu_read_lock_any_held() can detect this.

Thanks,
Sandeep.

> Or do you have better ideas?
>
> Thanks,
> Gao Xiang
>
> >
> > Thanks,
> > Sandeep.


More information about the Linux-erofs mailing list