On Fri, 2018-07-27 at 09:57 +-0800, jianchao.wang wrote: +AD4- Something like: +AD4- +AD4- percpu+AF8-ref+AF8-switch+AF8-to+AF8-atomic+AF8-sync(+ACY-q-+AD4-q+AF8-usage+AF8-counter)+ADs- +AD4- if (+ACE-percpu+AF8-ref+AF8-is+AF8-zero(+ACY-q-+AD4-q+AF8-usage+AF8-counter)) +AHs- +AD4- ret +AD0- -EBUSY+ADs- +AD4- pm+AF8-runtime+AF8-mark+AF8-last+AF8-busy(q-+AD4-dev)+ADs- +AD4- +AH0- else +AHs- +AD4- blk+AF8-set+AF8-preempt+AF8-only(q)+ADs- +AD4- if (+ACE-percpu+AF8-ref+AF8-is+AF8-zero(+ACY-q-+AD4-q+AF8-usage+AF8-counter) +AHs- +AD4- ret +AD0- -EBUSY+ADs- +AD4- pm+AF8-runtime+AF8-mark+AF8-last+AF8-busy(q-+AD4-dev)+ADs- +AD4- blk+AF8-clear+AF8-preempt+AF8-only(q)+ADs- +AD4- +AH0- else +AHs- +AD4- q-+AD4-rpm+AF8-status +AD0- RPM+AF8-SUSPENDIN+ADs- +AD4- +AH0- +AD4- +AH0- I think this code is racy. Because there is no memory barrier in blk+AF8-queue+AF8-enter() between the percpu+AF8-ref+AF8-tryget+AF8-live() and the blk+AF8-queue+AF8-preempt+AF8-only() calls, the context that sets the PREEMPT+AF8-ONLY flag has to use synchronize+AF8-rcu() or call+AF8-rcu() to ensure that blk+AF8-queue+AF8-enter() sees the PREEMPT+AF8-ONLY flag after it has called percpu+AF8-ref+AF8-tryget+AF8-live(). See also http://lwn.net/Articles/573497/. Bart.