Re: [PATCH 10/11] treewide: Manually convert custom kernel_param_ops .get callbacks

"Rafael J. Wysocki" <[email protected]>
Newsgroups org.infradead.lists.linux-um,dev.linux.lists.virtualization,org.freedesktop.lists.dri-devel,org.freedesktop.lists.intel-gfx,org.kernel.vger.dmaengine,org.kernel.vger.kvm,org.kernel.vger.linux-acpi,org.kernel.vger.linux-arch,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-hardening,org.kernel.vger.linux-kernel,org.kernel.vger.linux-media,org.kernel.vger.linux-modules,org.kernel.vger.linux-pci,org.kernel.vger.linux-pm,org.kernel.vger.linux-rdma,org.kernel.vger.linux-scsi,org.kernel.vger.linux-security-module,org.kernel.vger.linux-serial,org.kernel.vger.linux-usb,org.kernel.vger.netdev,org.kvack.linux-mm,org.nongnu.qemu-devel,org.ozlabs.lists.linuxppc-dev
Message-ID <CAJZ5v0gzCFu8Simqco8QZPU3-jmUSxhK_zsx4FqCrgLXQ5-UvQ@mail.gmail.com>
On Thu, May 21, 2026 at 3:33 PM Kees Cook <[email protected]> wrote:
>
> Convert struct kernel_param_ops .get callbacks from legacy "char *" to
> "struct seq_buf *".
>
> Since seq_buf_printf() will return -1 on overflow, and struct
> kernel_param_ops .get callbacks are expected to truncate without error,
> we must ignore the return value from seq_buf_print() and always return 0
> (as the length is calculated in the common dispatcher code).
>
> No struct kernel_param_ops initializations need changing since
> DEFINE_KERNEL_PARAM_OPS already routes the pointer to .get or .get_str
> via _Generic based on the function signature, so converted callbacks
> are automatically moved from the .get_str to the .get callback.
>
> Signed-off-by: Kees Cook <[email protected]>

For ACPI:

Acked-by: Rafael J. Wysocki (Intel) <[email protected]>

> ---
>  include/linux/dynamic_debug.h            |  8 ++-
>  arch/um/drivers/vfio_kern.c              |  3 +-
>  arch/um/drivers/virtio_uml.c             | 12 ++--
>  drivers/acpi/button.c                    | 19 ++++--
>  drivers/acpi/sysfs.c                     | 83 +++++++++++-------------
>  drivers/char/ipmi/ipmi_watchdog.c        | 33 ++++------
>  drivers/firmware/qemu_fw_cfg.c           | 34 +++++-----
>  drivers/gpu/drm/i915/i915_mitigations.c  | 26 ++++----
>  drivers/infiniband/ulp/srp/ib_srp.c      |  7 +-
>  drivers/media/usb/uvc/uvc_driver.c       |  8 ++-
>  drivers/pci/pcie/aspm.c                  | 17 +++--
>  drivers/scsi/fcoe/fcoe_transport.c       | 22 +++----
>  drivers/thermal/intel/intel_powerclamp.c | 14 ++--
>  drivers/tty/hvc/hvc_iucv.c               | 18 ++---
>  drivers/usb/storage/usb.c                | 20 +++---
>  drivers/virtio/virtio_mmio.c             | 21 +++---
>  lib/dynamic_debug.c                      | 10 ++-
>  17 files changed, 178 insertions(+), 177 deletions(-)
>
> diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
> index 05743900a116..999a25671b6a 100644
> --- a/include/linux/dynamic_debug.h
> +++ b/include/linux/dynamic_debug.h
> @@ -334,8 +334,10 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
>  extern int ddebug_dyndbg_module_param_cb(char *param, char *val,
>                                         const char *modname);
>  struct kernel_param;
> +struct seq_buf;
>  int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp);
> -int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp);
> +int param_get_dyndbg_classes(struct seq_buf *buffer,
> +                            const struct kernel_param *kp);
>
>  #else
>
> @@ -352,9 +354,11 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,
>  }
>
>  struct kernel_param;
> +struct seq_buf;
>  static inline int param_set_dyndbg_classes(const char *instr, const struct kernel_param *kp)
>  { return 0; }
> -static inline int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
> +static inline int param_get_dyndbg_classes(struct seq_buf *buffer,
> +                                          const struct kernel_param *kp)
>  { return 0; }
>
>  #endif
> diff --git a/arch/um/drivers/vfio_kern.c b/arch/um/drivers/vfio_kern.c
> index fb7988dc5482..7c1119d0d9c1 100644
> --- a/arch/um/drivers/vfio_kern.c
> +++ b/arch/um/drivers/vfio_kern.c
> @@ -623,7 +623,8 @@ static int uml_vfio_cmdline_set(const char *device, const struct kernel_param *k
>         return 0;
>  }
>
> -static int uml_vfio_cmdline_get(char *buffer, const struct kernel_param *kp)
> +static int uml_vfio_cmdline_get(struct seq_buf *buffer,
> +                               const struct kernel_param *kp)
>  {
>         return 0;
>  }
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index f9ae745f4586..cea806540625 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -1379,23 +1379,21 @@ static int vu_cmdline_get_device(struct device *dev, void *data)
>  {
>         struct platform_device *pdev = to_platform_device(dev);
>         struct virtio_uml_platform_data *pdata = pdev->dev.platform_data;
> -       char *buffer = data;
> -       unsigned int len = strlen(buffer);
> +       struct seq_buf *s = data;
>
> -       snprintf(buffer + len, PAGE_SIZE - len, "%s:%d:%d\n",
> -                pdata->socket_path, pdata->virtio_device_id, pdev->id);
> +       seq_buf_printf(s, "%s:%d:%d\n",
> +                      pdata->socket_path, pdata->virtio_device_id, pdev->id);
>         return 0;
>  }
>
> -static int vu_cmdline_get(char *buffer, const struct kernel_param *kp)
> +static int vu_cmdline_get(struct seq_buf *buffer, const struct kernel_param *kp)
>  {
>         guard(mutex)(&vu_cmdline_lock);
>
> -       buffer[0] = '\0';
>         if (vu_cmdline_parent_registered)
>                 device_for_each_child(&vu_cmdline_parent, buffer,
>                                       vu_cmdline_get_device);
> -       return strlen(buffer) + 1;
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(vu_cmdline_param_ops, vu_cmdline_set,
> diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
> index dc064a388c23..31c624bebc65 100644
> --- a/drivers/acpi/button.c
> +++ b/drivers/acpi/button.c
> @@ -715,19 +715,24 @@ static int param_set_lid_init_state(const char *val,
>         return 0;
>  }
>
> -static int param_get_lid_init_state(char *buf, const struct kernel_param *kp)
> +static int param_get_lid_init_state(struct seq_buf *buf,
> +                                   const struct kernel_param *kp)
>  {
> -       int i, c = 0;
> +       int i;
>
> -       for (i = 0; i < ARRAY_SIZE(lid_init_state_str); i++)
> +       for (i = 0; i < ARRAY_SIZE(lid_init_state_str); i++) {
>                 if (i == lid_init_state)
> -                       c += sprintf(buf + c, "[%s] ", lid_init_state_str[i]);
> +                       seq_buf_printf(buf, "[%s] ", lid_init_state_str[i]);
>                 else
> -                       c += sprintf(buf + c, "%s ", lid_init_state_str[i]);
> +                       seq_buf_printf(buf, "%s ", lid_init_state_str[i]);
> +       }
>
> -       buf[c - 1] = '\n'; /* Replace the final space with a newline */
> +       /* Replace the final space with a newline. */
> +       if (!seq_buf_has_overflowed(buf) && buf->len > 0 &&
> +           buf->buffer[buf->len - 1] == ' ')
> +               buf->buffer[buf->len - 1] = '\n';
>
> -       return c;
> +       return 0;
>  }
>
>  module_param_call(lid_init_state,
> diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
> index 5247ed7e05cc..dff7cc7da8bf 100644
> --- a/drivers/acpi/sysfs.c
> +++ b/drivers/acpi/sysfs.c
> @@ -89,53 +89,49 @@ static const struct acpi_dlevel acpi_debug_levels[] = {
>         ACPI_DEBUG_INIT(ACPI_LV_EVENTS),
>  };
>
> -static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
> +static int param_get_debug_layer(struct seq_buf *buffer,
> +                                const struct kernel_param *kp)
>  {
> -       int result = 0;
>         int i;
>
> -       result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
> +       seq_buf_printf(buffer, "%-25s\tHex        SET\n", "Description");
>
>         for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
> -               result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
> -                                 acpi_debug_layers[i].name,
> -                                 acpi_debug_layers[i].value,
> -                                 (acpi_dbg_layer & acpi_debug_layers[i].value)
> -                                 ? '*' : ' ');
> +               seq_buf_printf(buffer, "%-25s\t0x%08lX [%c]\n",
> +                              acpi_debug_layers[i].name,
> +                              acpi_debug_layers[i].value,
> +                              (acpi_dbg_layer & acpi_debug_layers[i].value)
> +                              ? '*' : ' ');
>         }
> -       result +=
> -           sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
> -                   ACPI_ALL_DRIVERS,
> -                   (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
> -                   ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS)
> -                   == 0 ? ' ' : '-');
> -       result +=
> -           sprintf(buffer + result,
> -                   "--\ndebug_layer = 0x%08X ( * = enabled)\n",
> -                   acpi_dbg_layer);
> +       seq_buf_printf(buffer, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
> +                      ACPI_ALL_DRIVERS,
> +                      (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS
> +                      ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0
> +                      ? ' ' : '-');
> +       seq_buf_printf(buffer, "--\ndebug_layer = 0x%08X ( * = enabled)\n",
> +                      acpi_dbg_layer);
>
> -       return result;
> +       return 0;
>  }
>
> -static int param_get_debug_level(char *buffer, const struct kernel_param *kp)
> +static int param_get_debug_level(struct seq_buf *buffer,
> +                                const struct kernel_param *kp)
>  {
> -       int result = 0;
>         int i;
>
> -       result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
> +       seq_buf_printf(buffer, "%-25s\tHex        SET\n", "Description");
>
>         for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) {
> -               result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
> -                                 acpi_debug_levels[i].name,
> -                                 acpi_debug_levels[i].value,
> -                                 (acpi_dbg_level & acpi_debug_levels[i].value)
> -                                 ? '*' : ' ');
> +               seq_buf_printf(buffer, "%-25s\t0x%08lX [%c]\n",
> +                              acpi_debug_levels[i].name,
> +                              acpi_debug_levels[i].value,
> +                              (acpi_dbg_level & acpi_debug_levels[i].value)
> +                              ? '*' : ' ');
>         }
> -       result +=
> -           sprintf(buffer + result, "--\ndebug_level = 0x%08X (* = enabled)\n",
> -                   acpi_dbg_level);
> +       seq_buf_printf(buffer, "--\ndebug_level = 0x%08X (* = enabled)\n",
> +                      acpi_dbg_level);
>
> -       return result;
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(param_ops_debug_layer, param_set_uint,
> @@ -247,16 +243,18 @@ static int param_set_trace_state(const char *val,
>         return 0;
>  }
>
> -static int param_get_trace_state(char *buffer, const struct kernel_param *kp)
> +static int param_get_trace_state(struct seq_buf *buffer,
> +                                const struct kernel_param *kp)
>  {
>         if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED))
> -               return sprintf(buffer, "disable\n");
> -       if (!acpi_gbl_trace_method_name)
> -               return sprintf(buffer, "enable\n");
> -       if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT)
> -               return sprintf(buffer, "method-once\n");
> +               seq_buf_printf(buffer, "disable\n");
> +       else if (!acpi_gbl_trace_method_name)
> +               seq_buf_printf(buffer, "enable\n");
> +       else if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT)
> +               seq_buf_printf(buffer, "method-once\n");
>         else
> -               return sprintf(buffer, "method\n");
> +               seq_buf_printf(buffer, "method\n");
> +       return 0;
>  }
>
>  module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
> @@ -272,14 +270,11 @@ MODULE_PARM_DESC(aml_debug_output,
>                  "To enable/disable the ACPI Debug Object output.");
>
>  /* /sys/module/acpi/parameters/acpica_version */
> -static int param_get_acpica_version(char *buffer,
> +static int param_get_acpica_version(struct seq_buf *buffer,
>                                     const struct kernel_param *kp)
>  {
> -       int result;
> -
> -       result = sprintf(buffer, "%x\n", ACPI_CA_VERSION);
> -
> -       return result;
> +       seq_buf_printf(buffer, "%x\n", ACPI_CA_VERSION);
> +       return 0;
>  }
>
>  module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
> diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
> index 91a99417d204..2bfec85ef331 100644
> --- a/drivers/char/ipmi/ipmi_watchdog.c
> +++ b/drivers/char/ipmi/ipmi_watchdog.c
> @@ -197,11 +197,11 @@ static DEFINE_KERNEL_PARAM_OPS(param_ops_timeout, set_param_timeout,
>                                param_get_int);
>  #define param_check_timeout param_check_int
>
> -typedef int (*action_fn)(const char *intval, char *outval);
> +typedef int (*action_fn)(const char *intval, struct seq_buf *outval);
>
> -static int action_op(const char *inval, char *outval);
> -static int preaction_op(const char *inval, char *outval);
> -static int preop_op(const char *inval, char *outval);
> +static int action_op(const char *inval, struct seq_buf *outval);
> +static int preaction_op(const char *inval, struct seq_buf *outval);
> +static int preop_op(const char *inval, struct seq_buf *outval);
>  static void check_parms(void);
>
>  static int set_param_str(const char *val, const struct kernel_param *kp)
> @@ -227,20 +227,11 @@ static int set_param_str(const char *val, const struct kernel_param *kp)
>         return rv;
>  }
>
> -static int get_param_str(char *buffer, const struct kernel_param *kp)
> +static int get_param_str(struct seq_buf *buffer, const struct kernel_param *kp)
>  {
>         action_fn fn = (action_fn) kp->arg;
> -       int rv, len;
>
> -       rv = fn(NULL, buffer);
> -       if (rv)
> -               return rv;
> -
> -       len = strlen(buffer);
> -       buffer[len++] = '\n';
> -       buffer[len] = 0;
> -
> -       return len;
> +       return fn(NULL, buffer);
>  }
>
>
> @@ -1154,12 +1145,12 @@ static int action_op_set_val(const char *inval)
>         return 0;
>  }
>
> -static int action_op(const char *inval, char *outval)
> +static int action_op(const char *inval, struct seq_buf *outval)
>  {
>         int rv;
>
>         if (outval)
> -               strcpy(outval, action);
> +               seq_buf_printf(outval, "%s\n", action);
>
>         if (!inval)
>                 return 0;
> @@ -1186,12 +1177,12 @@ static int preaction_op_set_val(const char *inval)
>         return 0;
>  }
>
> -static int preaction_op(const char *inval, char *outval)
> +static int preaction_op(const char *inval, struct seq_buf *outval)
>  {
>         int rv;
>
>         if (outval)
> -               strcpy(outval, preaction);
> +               seq_buf_printf(outval, "%s\n", preaction);
>
>         if (!inval)
>                 return 0;
> @@ -1214,12 +1205,12 @@ static int preop_op_set_val(const char *inval)
>         return 0;
>  }
>
> -static int preop_op(const char *inval, char *outval)
> +static int preop_op(const char *inval, struct seq_buf *outval)
>  {
>         int rv;
>
>         if (outval)
> -               strcpy(outval, preop);
> +               seq_buf_printf(outval, "%s\n", preop);
>
>         if (!inval)
>                 return 0;
> diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
> index c87a5449ba8c..4ebc1e327849 100644
> --- a/drivers/firmware/qemu_fw_cfg.c
> +++ b/drivers/firmware/qemu_fw_cfg.c
> @@ -860,7 +860,8 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp)
>         return PTR_ERR_OR_ZERO(fw_cfg_cmdline_dev);
>  }
>
> -static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
> +static int fw_cfg_cmdline_get(struct seq_buf *buf,
> +                             const struct kernel_param *kp)
>  {
>         /* stay silent if device was not configured via the command
>          * line, or if the parameter name (ioport/mmio) doesn't match
> @@ -873,22 +874,25 @@ static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp)
>
>         switch (fw_cfg_cmdline_dev->num_resources) {
>         case 1:
> -               return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_1_FMT,
> -                               resource_size(&fw_cfg_cmdline_dev->resource[0]),
> -                               fw_cfg_cmdline_dev->resource[0].start);
> +               seq_buf_printf(buf, PH_ADDR_PR_1_FMT,
> +                              resource_size(&fw_cfg_cmdline_dev->resource[0]),
> +                              fw_cfg_cmdline_dev->resource[0].start);
> +               return 0;
>         case 3:
> -               return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_3_FMT,
> -                               resource_size(&fw_cfg_cmdline_dev->resource[0]),
> -                               fw_cfg_cmdline_dev->resource[0].start,
> -                               fw_cfg_cmdline_dev->resource[1].start,
> -                               fw_cfg_cmdline_dev->resource[2].start);
> +               seq_buf_printf(buf, PH_ADDR_PR_3_FMT,
> +                              resource_size(&fw_cfg_cmdline_dev->resource[0]),
> +                              fw_cfg_cmdline_dev->resource[0].start,
> +                              fw_cfg_cmdline_dev->resource[1].start,
> +                              fw_cfg_cmdline_dev->resource[2].start);
> +               return 0;
>         case 4:
> -               return snprintf(buf, PAGE_SIZE, PH_ADDR_PR_4_FMT,
> -                               resource_size(&fw_cfg_cmdline_dev->resource[0]),
> -                               fw_cfg_cmdline_dev->resource[0].start,
> -                               fw_cfg_cmdline_dev->resource[1].start,
> -                               fw_cfg_cmdline_dev->resource[2].start,
> -                               fw_cfg_cmdline_dev->resource[3].start);
> +               seq_buf_printf(buf, PH_ADDR_PR_4_FMT,
> +                              resource_size(&fw_cfg_cmdline_dev->resource[0]),
> +                              fw_cfg_cmdline_dev->resource[0].start,
> +                              fw_cfg_cmdline_dev->resource[1].start,
> +                              fw_cfg_cmdline_dev->resource[2].start,
> +                              fw_cfg_cmdline_dev->resource[3].start);
> +               return 0;
>         }
>
>         /* Should never get here */
> diff --git a/drivers/gpu/drm/i915/i915_mitigations.c b/drivers/gpu/drm/i915/i915_mitigations.c
> index 6061eae84e9c..99cb38f355b6 100644
> --- a/drivers/gpu/drm/i915/i915_mitigations.c
> +++ b/drivers/gpu/drm/i915/i915_mitigations.c
> @@ -95,33 +95,37 @@ static int mitigations_set(const char *val, const struct kernel_param *kp)
>         return 0;
>  }
>
> -static int mitigations_get(char *buffer, const struct kernel_param *kp)
> +static int mitigations_get(struct seq_buf *buffer,
> +                          const struct kernel_param *kp)
>  {
>         unsigned long local = READ_ONCE(mitigations);
> -       int count, i;
>         bool enable;
> +       int i;
>
> -       if (!local)
> -               return scnprintf(buffer, PAGE_SIZE, "%s\n", "off");
> +       if (!local) {
> +               seq_buf_printf(buffer, "%s\n", "off");
> +               return 0;
> +       }
>
>         if (local & BIT(BITS_PER_LONG - 1)) {
> -               count = scnprintf(buffer, PAGE_SIZE, "%s,", "auto");
> +               seq_buf_printf(buffer, "%s,", "auto");
>                 enable = false;
>         } else {
>                 enable = true;
> -               count = 0;
>         }
>
>         for (i = 0; i < ARRAY_SIZE(names); i++) {
>                 if ((local & BIT(i)) != enable)
>                         continue;
> -
> -               count += scnprintf(buffer + count, PAGE_SIZE - count,
> -                                  "%s%s,", enable ? "" : "!", names[i]);
> +               seq_buf_printf(buffer, "%s%s,", enable ? "" : "!", names[i]);
>         }
>
> -       buffer[count - 1] = '\n';
> -       return count;
> +       /* Replace the trailing comma with a newline. */
> +       if (!seq_buf_has_overflowed(buffer) && buffer->len > 0 &&
> +           buffer->buffer[buffer->len - 1] == ',')
> +               buffer->buffer[buffer->len - 1] = '\n';
> +
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(ops, mitigations_set, mitigations_get);
> diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
> index a81515f52a4f..4f53e939eec1 100644
> --- a/drivers/infiniband/ulp/srp/ib_srp.c
> +++ b/drivers/infiniband/ulp/srp/ib_srp.c
> @@ -161,14 +161,15 @@ static struct ib_client srp_client = {
>
>  static struct ib_sa_client srp_sa_client;
>
> -static int srp_tmo_get(char *buffer, const struct kernel_param *kp)
> +static int srp_tmo_get(struct seq_buf *buffer, const struct kernel_param *kp)
>  {
>         int tmo = *(int *)kp->arg;
>
>         if (tmo >= 0)
> -               return sysfs_emit(buffer, "%d\n", tmo);
> +               seq_buf_printf(buffer, "%d\n", tmo);
>         else
> -               return sysfs_emit(buffer, "off\n");
> +               seq_buf_printf(buffer, "off\n");
> +       return 0;
>  }
>
>  static int srp_tmo_set(const char *val, const struct kernel_param *kp)
> diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
> index 2338cab7fef9..1c5c40ce852d 100644
> --- a/drivers/media/usb/uvc/uvc_driver.c
> +++ b/drivers/media/usb/uvc/uvc_driver.c
> @@ -2451,12 +2451,14 @@ static int uvc_reset_resume(struct usb_interface *intf)
>   * Module parameters
>   */
>
> -static int uvc_clock_param_get(char *buffer, const struct kernel_param *kp)
> +static int uvc_clock_param_get(struct seq_buf *buffer,
> +                              const struct kernel_param *kp)
>  {
>         if (uvc_clock_param == CLOCK_MONOTONIC)
> -               return sprintf(buffer, "CLOCK_MONOTONIC");
> +               seq_buf_printf(buffer, "CLOCK_MONOTONIC");
>         else
> -               return sprintf(buffer, "CLOCK_REALTIME");
> +               seq_buf_printf(buffer, "CLOCK_REALTIME");
> +       return 0;
>  }
>
>  static int uvc_clock_param_set(const char *val, const struct kernel_param *kp)
> diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
> index 925373b98dff..af2dd668fe4d 100644
> --- a/drivers/pci/pcie/aspm.c
> +++ b/drivers/pci/pcie/aspm.c
> @@ -1572,16 +1572,19 @@ static int pcie_aspm_set_policy(const char *val,
>         return 0;
>  }
>
> -static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp)
> +static int pcie_aspm_get_policy(struct seq_buf *buffer,
> +                               const struct kernel_param *kp)
>  {
> -       int i, cnt = 0;
> -       for (i = 0; i < ARRAY_SIZE(policy_str); i++)
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(policy_str); i++) {
>                 if (i == aspm_policy)
> -                       cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
> +                       seq_buf_printf(buffer, "[%s] ", policy_str[i]);
>                 else
> -                       cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
> -       cnt += sprintf(buffer + cnt, "\n");
> -       return cnt;
> +                       seq_buf_printf(buffer, "%s ", policy_str[i]);
> +       }
> +       seq_buf_putc(buffer, '\n');
> +       return 0;
>  }
>
>  module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
> diff --git a/drivers/scsi/fcoe/fcoe_transport.c b/drivers/scsi/fcoe/fcoe_transport.c
> index 88d85fc9a52a..aa10514ec46e 100644
> --- a/drivers/scsi/fcoe/fcoe_transport.c
> +++ b/drivers/scsi/fcoe/fcoe_transport.c
> @@ -23,7 +23,8 @@ MODULE_LICENSE("GPL v2");
>
>  static int fcoe_transport_create(const char *, const struct kernel_param *);
>  static int fcoe_transport_destroy(const char *, const struct kernel_param *);
> -static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
> +static int fcoe_transport_show(struct seq_buf *buffer,
> +                              const struct kernel_param *kp);
>  static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
>  static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
>  static int fcoe_transport_enable(const char *, const struct kernel_param *);
> @@ -595,22 +596,21 @@ int fcoe_transport_detach(struct fcoe_transport *ft)
>  }
>  EXPORT_SYMBOL(fcoe_transport_detach);
>
> -static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
> +static int fcoe_transport_show(struct seq_buf *buffer,
> +                              const struct kernel_param *kp)
>  {
> -       int i, j;
>         struct fcoe_transport *ft = NULL;
>
> -       i = j = sprintf(buffer, "Attached FCoE transports:");
> +       seq_buf_printf(buffer, "Attached FCoE transports:");
>         mutex_lock(&ft_mutex);
> -       list_for_each_entry(ft, &fcoe_transports, list) {
> -               if (i >= PAGE_SIZE - IFNAMSIZ)
> -                       break;
> -               i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
> +       if (list_empty(&fcoe_transports)) {
> +               seq_buf_printf(buffer, "none");
> +       } else {
> +               list_for_each_entry(ft, &fcoe_transports, list)
> +                       seq_buf_printf(buffer, "%s ", ft->name);
>         }
>         mutex_unlock(&ft_mutex);
> -       if (i == j)
> -               i += snprintf(&buffer[i], IFNAMSIZ, "none");
> -       return i;
> +       return 0;
>  }
>
>  static int __init fcoe_transport_init(void)
> diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c
> index 98fbc6892714..50ec1a0ff1ab 100644
> --- a/drivers/thermal/intel/intel_powerclamp.c
> +++ b/drivers/thermal/intel/intel_powerclamp.c
> @@ -101,15 +101,13 @@ static int duration_set(const char *arg, const struct kernel_param *kp)
>         return ret;
>  }
>
> -static int duration_get(char *buf, const struct kernel_param *kp)
> +static int duration_get(struct seq_buf *buf, const struct kernel_param *kp)
>  {
> -       int ret;
> -
>         mutex_lock(&powerclamp_lock);
> -       ret = sysfs_emit(buf, "%d\n", duration / 1000);
> +       seq_buf_printf(buf, "%d\n", duration / 1000);
>         mutex_unlock(&powerclamp_lock);
>
> -       return ret;
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(duration_ops, duration_set, duration_get);
> @@ -192,12 +190,14 @@ static int cpumask_set(const char *arg, const struct kernel_param *kp)
>         return ret;
>  }
>
> -static int cpumask_get(char *buf, const struct kernel_param *kp)
> +static int cpumask_get(struct seq_buf *buf, const struct kernel_param *kp)
>  {
>         if (!cpumask_available(idle_injection_cpu_mask))
>                 return -ENODEV;
>
> -       return cpumap_print_to_pagebuf(false, buf, idle_injection_cpu_mask);
> +       seq_buf_printf(buf, "%*pb\n", nr_cpu_ids,
> +                      cpumask_bits(idle_injection_cpu_mask));
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(cpumask_ops, cpumask_set, cpumask_get);
> diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
> index 29612a4a32cb..b27c1dfbd249 100644
> --- a/drivers/tty/hvc/hvc_iucv.c
> +++ b/drivers/tty/hvc/hvc_iucv.c
> @@ -1256,36 +1256,32 @@ static int param_set_vmidfilter(const char *val, const struct kernel_param *kp)
>
>  /**
>   * param_get_vmidfilter() - Get z/VM user ID filter
> - * @buffer:    Buffer to store z/VM user ID filter,
> - *             (buffer size assumption PAGE_SIZE)
> + * @buffer:    seq_buf to store z/VM user ID filter
>   * @kp:                Kernel parameter pointing to the hvc_iucv_filter array
>   *
>   * The function stores the filter as a comma-separated list of z/VM user IDs
>   * in @buffer. Typically, sysfs routines call this function for attr show.
>   */
> -static int param_get_vmidfilter(char *buffer, const struct kernel_param *kp)
> +static int param_get_vmidfilter(struct seq_buf *buffer,
> +                               const struct kernel_param *kp)
>  {
> -       int rc;
>         size_t index, len;
>         void *start, *end;
>
>         if (!machine_is_vm() || !hvc_iucv_devices)
>                 return -ENODEV;
>
> -       rc = 0;
>         read_lock_bh(&hvc_iucv_filter_lock);
>         for (index = 0; index < hvc_iucv_filter_size; index++) {
>                 start = hvc_iucv_filter + (8 * index);
>                 end   = memchr(start, ' ', 8);
>                 len   = (end) ? end - start : 8;
> -               memcpy(buffer + rc, start, len);
> -               rc += len;
> -               buffer[rc++] = ',';
> +               if (index)
> +                       seq_buf_putc(buffer, ',');
> +               seq_buf_printf(buffer, "%.*s", (int)len, (char *)start);
>         }
>         read_unlock_bh(&hvc_iucv_filter_lock);
> -       if (rc)
> -               buffer[--rc] = '\0';    /* replace last comma and update rc */
> -       return rc;
> +       return 0;
>  }
>
>  #define param_check_vmidfilter(name, p) __param_check(name, p, void)
> diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
> index 71dd623b95c9..637e1b8f622f 100644
> --- a/drivers/usb/storage/usb.c
> +++ b/drivers/usb/storage/usb.c
> @@ -115,27 +115,22 @@ static int parse_delay_str(const char *str, int ndecimals, const char *suffix,
>   * @val: The integer value to format, scaled by 10^(@ndecimals).
>   * @ndecimals: Number of decimal to scale down.
>   * @suffix: Suffix string to format.
> - * @str: Where to store the formatted string.
> - * @size: The size of buffer for @str.
> + * @s: Where to store the formatted string.
>   *
>   * Format an integer value in @val scale down by 10^(@ndecimals) without @suffix
>   * if @val is divisible by 10^(@ndecimals).
>   * Otherwise format a value in @val just as it is with @suffix
> - *
> - * Returns the number of characters written into @str.
>   */
> -static int format_delay_ms(unsigned int val, int ndecimals, const char *suffix,
> -                       char *str, int size)
> +static void format_delay_ms(unsigned int val, int ndecimals, const char *suffix,
> +                           struct seq_buf *s)
>  {
>         u64 delay_ms = val;
>         unsigned int rem = do_div(delay_ms, int_pow(10, ndecimals));
> -       int ret;
>
>         if (rem)
> -               ret = scnprintf(str, size, "%u%s\n", val, suffix);
> +               seq_buf_printf(s, "%u%s\n", val, suffix);
>         else
> -               ret = scnprintf(str, size, "%u\n", (unsigned int)delay_ms);
> -       return ret;
> +               seq_buf_printf(s, "%u\n", (unsigned int)delay_ms);
>  }
>
>  static int delay_use_set(const char *s, const struct kernel_param *kp)
> @@ -151,11 +146,12 @@ static int delay_use_set(const char *s, const struct kernel_param *kp)
>         return 0;
>  }
>
> -static int delay_use_get(char *s, const struct kernel_param *kp)
> +static int delay_use_get(struct seq_buf *s, const struct kernel_param *kp)
>  {
>         unsigned int delay_ms = *((unsigned int *)kp->arg);
>
> -       return format_delay_ms(delay_ms, 3, "ms", s, PAGE_SIZE);
> +       format_delay_ms(delay_ms, 3, "ms", s);
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(delay_use_ops, delay_use_set, delay_use_get);
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index f6df9c76ee81..81a7455e4643 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -728,24 +728,21 @@ static int vm_cmdline_set(const char *device,
>
>  static int vm_cmdline_get_device(struct device *dev, void *data)
>  {
> -       char *buffer = data;
> -       unsigned int len = strlen(buffer);
> +       struct seq_buf *s = data;
>         struct platform_device *pdev = to_platform_device(dev);
>
> -       snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n",
> -                       pdev->resource[0].end - pdev->resource[0].start + 1ULL,
> -                       (unsigned long long)pdev->resource[0].start,
> -                       (unsigned long long)pdev->resource[1].start,
> -                       pdev->id);
> +       seq_buf_printf(s, "0x%llx@0x%llx:%llu:%d\n",
> +                      pdev->resource[0].end - pdev->resource[0].start + 1ULL,
> +                      (unsigned long long)pdev->resource[0].start,
> +                      (unsigned long long)pdev->resource[1].start,
> +                      pdev->id);
>         return 0;
>  }
>
> -static int vm_cmdline_get(char *buffer, const struct kernel_param *kp)
> +static int vm_cmdline_get(struct seq_buf *s, const struct kernel_param *kp)
>  {
> -       buffer[0] = '\0';
> -       device_for_each_child(&vm_cmdline_parent, buffer,
> -                       vm_cmdline_get_device);
> -       return strlen(buffer) + 1;
> +       device_for_each_child(&vm_cmdline_parent, s, vm_cmdline_get_device);
> +       return 0;
>  }
>
>  static DEFINE_KERNEL_PARAM_OPS(vm_cmdline_param_ops, vm_cmdline_set,
> diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
> index cf0405ba0dbd..123f061c2fb2 100644
> --- a/lib/dynamic_debug.c
> +++ b/lib/dynamic_debug.c
> @@ -17,6 +17,7 @@
>  #include <linux/module.h>
>  #include <linux/moduleparam.h>
>  #include <linux/kallsyms.h>
> +#include <linux/seq_buf.h>
>  #include <linux/types.h>
>  #include <linux/mutex.h>
>  #include <linux/proc_fs.h>
> @@ -787,7 +788,8 @@ EXPORT_SYMBOL(param_set_dyndbg_classes);
>   * altered by direct >control.  Displays 0x for DISJOINT, 0-N for
>   * LEVEL Returns: #chars written or <0 on error
>   */
> -int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
> +int param_get_dyndbg_classes(struct seq_buf *buffer,
> +                            const struct kernel_param *kp)
>  {
>         const struct ddebug_class_param *dcp = kp->arg;
>         const struct ddebug_class_map *map = dcp->map;
> @@ -796,11 +798,13 @@ int param_get_dyndbg_classes(char *buffer, const struct kernel_param *kp)
>
>         case DD_CLASS_TYPE_DISJOINT_NAMES:
>         case DD_CLASS_TYPE_DISJOINT_BITS:
> -               return scnprintf(buffer, PAGE_SIZE, "0x%lx\n", *dcp->bits);
> +               seq_buf_printf(buffer, "0x%lx\n", *dcp->bits);
> +               return 0;
>
>         case DD_CLASS_TYPE_LEVEL_NAMES:
>         case DD_CLASS_TYPE_LEVEL_NUM:
> -               return scnprintf(buffer, PAGE_SIZE, "%d\n", *dcp->lvl);
> +               seq_buf_printf(buffer, "%d\n", *dcp->lvl);
> +               return 0;
>         default:
>                 return -1;
>         }
> --
> 2.34.1
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.