Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sysfs: Add sysfs_bin_attr_simple_read() helper

When drivers expose a bin_attribute in sysfs which is backed by a buffer
in memory, a common pattern is to set the @private and @size members in
struct bin_attribute to the buffer's location and size.

The ->read() callback then merely consists of a single memcpy() call.
It's not even necessary to perform bounds checks as these are already
handled by sysfs_kf_bin_read().

However each driver is so far providing its own ->read() implementation.
The pattern is sufficiently frequent to merit a public helper, so add
sysfs_bin_attr_simple_read() as well as BIN_ATTR_SIMPLE_RO() and
BIN_ATTR_SIMPLE_ADMIN_RO() macros to ease declaration of such
bin_attributes and reduce LoC and .text section size.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/5ed62b197a442ec6db53d8746d9d806dd0576e2d.1712410202.git.lukas@wunner.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Lukas Wunner and committed by
Greg Kroah-Hartman
d48c0319 85d2b0aa

+42
+27
fs/sysfs/file.c
··· 783 783 return len; 784 784 } 785 785 EXPORT_SYMBOL_GPL(sysfs_emit_at); 786 + 787 + /** 788 + * sysfs_bin_attr_simple_read - read callback to simply copy from memory. 789 + * @file: attribute file which is being read. 790 + * @kobj: object to which the attribute belongs. 791 + * @attr: attribute descriptor. 792 + * @buf: destination buffer. 793 + * @off: offset in bytes from which to read. 794 + * @count: maximum number of bytes to read. 795 + * 796 + * Simple ->read() callback for bin_attributes backed by a buffer in memory. 797 + * The @private and @size members in struct bin_attribute must be set to the 798 + * buffer's location and size before the bin_attribute is created in sysfs. 799 + * 800 + * Bounds check for @off and @count is done in sysfs_kf_bin_read(). 801 + * Negative value check for @off is done in vfs_setpos() and default_llseek(). 802 + * 803 + * Returns number of bytes written to @buf. 804 + */ 805 + ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj, 806 + struct bin_attribute *attr, char *buf, 807 + loff_t off, size_t count) 808 + { 809 + memcpy(buf, attr->private + off, count); 810 + return count; 811 + } 812 + EXPORT_SYMBOL_GPL(sysfs_bin_attr_simple_read);
+15
include/linux/sysfs.h
··· 371 371 #define BIN_ATTR_ADMIN_RW(_name, _size) \ 372 372 struct bin_attribute bin_attr_##_name = __BIN_ATTR_ADMIN_RW(_name, _size) 373 373 374 + #define __BIN_ATTR_SIMPLE_RO(_name, _mode) { \ 375 + .attr = { .name = __stringify(_name), .mode = _mode }, \ 376 + .read = sysfs_bin_attr_simple_read, \ 377 + } 378 + 379 + #define BIN_ATTR_SIMPLE_RO(_name) \ 380 + struct bin_attribute bin_attr_##_name = __BIN_ATTR_SIMPLE_RO(_name, 0444) 381 + 382 + #define BIN_ATTR_SIMPLE_ADMIN_RO(_name) \ 383 + struct bin_attribute bin_attr_##_name = __BIN_ATTR_SIMPLE_RO(_name, 0400) 384 + 374 385 struct sysfs_ops { 375 386 ssize_t (*show)(struct kobject *, struct attribute *, char *); 376 387 ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t); ··· 488 477 int sysfs_emit(char *buf, const char *fmt, ...); 489 478 __printf(3, 4) 490 479 int sysfs_emit_at(char *buf, int at, const char *fmt, ...); 480 + 481 + ssize_t sysfs_bin_attr_simple_read(struct file *file, struct kobject *kobj, 482 + struct bin_attribute *attr, char *buf, 483 + loff_t off, size_t count); 491 484 492 485 #else /* CONFIG_SYSFS */ 493 486