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

Reply via email to