sysfs: bin_attribute: add const read/write callback variants

To make it possible to put struct bin_attribute into read-only memory,
the sysfs core has to stop passing mutable pointers to the read() and
write() callbacks.
As there are numerous implementors of these callbacks throughout the
tree it's not possible to change all of them at once.
To enable a step-by-step transition, add new variants of the read() and
write() callbacks which differ only in the constness of the struct
bin_attribute argument.

As most binary attributes are defined through macros, extend these
macros to transparently handle both variants of callbacks to minimize
the churn during the transition.
As soon as all handlers are switch to the const variant, the non-const
one can be removed together with the transition machinery.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
Acked-by: Krzysztof Wilczyński <kw@linux.com>
Link: https://lore.kernel.org/r/20241103-sysfs-const-bin_attr-v2-9-71110628844c@weissschuh.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Thomas Weißschuh 2024-11-03 17:03:38 +00:00 committed by Greg Kroah-Hartman
parent ae587a5099
commit eb2e6c3a8d
2 changed files with 40 additions and 7 deletions

View File

@ -91,9 +91,12 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
count = size - pos;
}
if (!battr->read)
if (!battr->read && !battr->read_new)
return -EIO;
if (battr->read_new)
return battr->read_new(of->file, kobj, battr, buf, pos, count);
return battr->read(of->file, kobj, battr, buf, pos, count);
}
@ -152,9 +155,12 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
if (!count)
return 0;
if (!battr->write)
if (!battr->write && !battr->write_new)
return -EIO;
if (battr->write_new)
return battr->write_new(of->file, kobj, battr, buf, pos, count);
return battr->write(of->file, kobj, battr, buf, pos, count);
}
@ -323,13 +329,19 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct kernfs_ops *ops;
struct kernfs_node *kn;
if (battr->read && battr->read_new)
return -EINVAL;
if (battr->write && battr->write_new)
return -EINVAL;
if (battr->mmap)
ops = &sysfs_bin_kfops_mmap;
else if (battr->read && battr->write)
else if ((battr->read || battr->read_new) && (battr->write || battr->write_new))
ops = &sysfs_bin_kfops_rw;
else if (battr->read)
else if (battr->read || battr->read_new)
ops = &sysfs_bin_kfops_ro;
else if (battr->write)
else if (battr->write || battr->write_new)
ops = &sysfs_bin_kfops_wo;
else
ops = &sysfs_file_kfops_empty;

View File

@ -305,8 +305,12 @@ struct bin_attribute {
struct address_space *(*f_mapping)(void);
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *,
char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
ssize_t (*write_new)(struct file *, struct kobject *,
const struct bin_attribute *, char *, loff_t, size_t);
loff_t (*llseek)(struct file *, struct kobject *, const struct bin_attribute *,
loff_t, int);
int (*mmap)(struct file *, struct kobject *, const struct bin_attribute *attr,
@ -325,11 +329,28 @@ struct bin_attribute {
*/
#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
typedef ssize_t __sysfs_bin_rw_handler_new(struct file *, struct kobject *,
const struct bin_attribute *, char *, loff_t, size_t);
/* macros to create static binary attributes easier */
#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \
.attr = { .name = __stringify(_name), .mode = _mode }, \
.read = _read, \
.write = _write, \
.read = _Generic(_read, \
__sysfs_bin_rw_handler_new * : NULL, \
default : _read \
), \
.read_new = _Generic(_read, \
__sysfs_bin_rw_handler_new * : _read, \
default : NULL \
), \
.write = _Generic(_write, \
__sysfs_bin_rw_handler_new * : NULL, \
default : _write \
), \
.write_new = _Generic(_write, \
__sysfs_bin_rw_handler_new * : _write, \
default : NULL \
), \
.size = _size, \
}