On Mon, Jul 27, 2026 at 12:29 PM Shrikanth Hegde <[email protected]> wrote:
> That means comparison is between preempt=voluntary vs preempt=lazy.
>
> If you make it full preemption in 6.15 you will likely see similar
> data as 7.1+. Only on 7.0/7.1 there is force switch to lazy/full.
> Can you give that a try?
>
> If it shows same data, that implies the regression is mainly due to
> change of preemption modes, rather than the static key stuff.

Tested on 7.1 by switching the runtime mode via
/sys/kernel/debug/sched/preempt:

Mode       kill bogo-ops/sec
----       -----------------
full       57,476
lazy       56,892
Delta      ~1% (noise)

The preemption mode (full vs lazy) makes no difference. The regression
is from CONFIG_PREEMPT_RCU being enabled, not from the choice of
preemption mode.

And as Christophe pointed out, it's CONFIG_PREEMPT_DYNAMIC that pulls
in CONFIG_PREEMPT_RCU, not CONFIG_PREEMPT_LAZY:

  config PREEMPT_RCU
        default y if (PREEMPT || PREEMPT_RT || PREEMPT_DYNAMIC)

So the chain is: your patch enables HAVE_PREEMPT_DYNAMIC_KEY ->
CONFIG_PREEMPT_DYNAMIC takes effect -> CONFIG_PREEMPT_RCU=y ->
expensive rcu_read_lock/unlock on ppc64le.

> Plus, it may call schedule in lazy/pull preemption.

The full vs lazy results above suggest extra scheduling is not a
significant factor here.

> This seems strange. How come rcu lock/unlock depends on SELinux
> policy? One should call rcu lock/unlock if they are working with
> rcu updated fields.
>
> Does the policy change itself protected with rcu lock/unlock?

The rcu_read_lock/unlock calls don't depend on SELinux policy -- they
are in the SELinux *code path* itself. SELinux uses RCU to protect
its AVC (Access Vector Cache) lookups. Every call to avc_has_perm()
takes rcu_read_lock() around the avc_lookup() hash table access.

When you boot with selinux=0, the SELinux LSM hooks are never called,
so the AVC code path (and its rcu_read_lock/unlock pairs) is never
reached. That's why disabling SELinux removes those call sites from
the hot path.

The call chain is:
  sys_kill -> check_kill_permission -> security_task_kill
    -> selinux_task_kill -> avc_has_perm
      -> rcu_read_lock()
      -> avc_lookup()    <-- hash table lookup under RCU protection
      -> rcu_read_unlock()

With selinux=0, security_task_kill() is essentially a no-op and none
of the avc/rcu code runs.

Jirka


Reply via email to