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 >
