On Thu, Oct 15, 2026 at 08:43:09PM +0800, Peng Wang wrote:
> Expose nohz_full_allowed under /sys/devices/system/cpu/ as the subset of
> nohz_full CPUs permitted to suppress their non-idle scheduler tick.
>
> Writes replace the entire list; reads report policy, not current tick
> state. Reject invalid input before updating policy. Document asynchronous
> revocation, offline CPU configuration and persistence across hotplug.
> The existing nohz_full attribute continues to report membership.
>
> Co-developed-by: He Rongguang <[email protected]>
> Signed-off-by: He Rongguang <[email protected]>
> Signed-off-by: Peng Wang <[email protected]>
> ---
> .../ABI/testing/sysfs-devices-system-cpu | 40 ++++++++++++++++
> drivers/base/cpu.c | 46 +++++++++++++++++++
> 2 files changed, 86 insertions(+)
>
> diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu
> b/Documentation/ABI/testing/sysfs-devices-system-cpu
> index 82d10d556cc89..edf3408fd84c8 100644
> --- a/Documentation/ABI/testing/sysfs-devices-system-cpu
> +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
> @@ -767,6 +767,46 @@ Description: Preferred MTE tag checking mode
>
> See also: Documentation/arch/arm64/memory-tagging-extension.rst
>
> +What: /sys/devices/system/cpu/nohz_full_allowed
> +Date: October 2026
> +Contact: Linux kernel mailing list <[email protected]>
> +Description:
> + (RW) CPUs permitted to stop the scheduler tick while non-idle.
> + Available with CONFIG_NO_HZ_FULL. The default is the complete
> + nohz_full CPU list. Readback reports permission, not the current
> + tick state: all the usual tick dependencies still apply.
> +
> + A write replaces the entire list, using CPU-list syntax (for
> + example, "1-3,5"). An empty line revokes permission from all
> + nohz_full CPUs. Invalid input is rejected without changing
> + policy. A parsed list containing CPUs outside nohz_full fails
> + with EINVAL. CPU numbers beyond the mask range and numeric
> + overflows are rejected by the CPU-list parser with ERANGE and
> + EOVERFLOW, respectively. Input must be shorter than PAGE_SIZE
> + bytes, otherwise E2BIG is returned. Embedded NULs and newlines
> + other than a trailing newline are rejected with EINVAL. Valid
> + writes without an active nohz_full configuration fail with
> + EOPNOTSUPP.
> +
> + Reads fail with EOVERFLOW if the formatted output reaches
> + PAGE_SIZE - 1 bytes, rather than returning a potentially
> + truncated CPU list.
> +
> + Revoking permission adds a per-CPU tick dependency. Online CPUs
> + are notified through the existing asynchronous kick mechanism
> + to restart a stopped non-idle tick. A successful write means
> + the policy is updated and any needed notification is queued;
> + it does not wait for tick restart. Changes to multiple CPUs
> + are not simultaneous. Granting permission only removes this
> + dependency and does not force the tick to stop.
> +
> + Offline CPUs may be configured without sending notifications.
> + Policy persists across CPU offline/online. Idle tick suppression
> + is unchanged; the policy applies when a CPU leaves idle.
> +
> + This interface does not change nohz_full membership, context
> + tracking, RCU offloading, or housekeeping configuration.
> +
> What: /sys/devices/system/cpu/nohz_full
> Date: Apr 2015
> Contact: Linux kernel mailing list <[email protected]>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 69e52fed42415..299ce61cef895 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -324,6 +324,51 @@ static ssize_t nohz_full_show(struct device *dev,
> return sysfs_emit(buf, "\n");
> }
> static DEVICE_ATTR_RO(nohz_full);
> +
> +static ssize_t nohz_full_allowed_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + cpumask_var_t mask;
> + ssize_t ret;
> +
> + if (!alloc_cpumask_var(&mask, GFP_KERNEL))
> + return -ENOMEM;
> +
> + tick_nohz_full_get_allowed(mask);
> + ret = sysfs_emit(buf, "%*pbl\n", cpumask_pr_args(mask));
> +
> + free_cpumask_var(mask);
> +
> + /* Never present a truncated CPU list as the complete policy. */
> + return ret == PAGE_SIZE - 1 ? -EOVERFLOW : ret;
Why not? What will userspace do then if it gets -EOVERFLOW as it can
not get the full list?
> +}
> +
> +static ssize_t nohz_full_allowed_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + cpumask_var_t mask;
> + int ret;
> +
> + /* kernfs may truncate an oversized write to PAGE_SIZE. */
> + if (count >= PAGE_SIZE)
> + return -E2BIG;
How are you getting a larger than PAGE_SIZE value here?
> + if (memchr(buf, '\0', count) ||
> + (count > 1 && memchr(buf, '\n', count - 1)))
> + return -EINVAL;
What are you testing for here, sorry, I can't easily figure it out.
thanks,
greg k-h