From 0afcee132bbc9d7ef9c5bb4da9b6fe014a9afaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sun, 3 Nov 2024 17:03:30 +0000 Subject: sysfs: explicitly pass size to sysfs_add_bin_file_mode_ns() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upcoming changes to the sysfs core require the size of the created file to be overridable by the caller. Add a parameter to enable this. For now keep using attr->size in all cases. Signed-off-by: Thomas Weißschuh Acked-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20241103-sysfs-const-bin_attr-v2-1-71110628844c@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 8 ++++---- fs/sysfs/group.c | 3 ++- fs/sysfs/sysfs.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index d1995e2d6c94..6d39696b4306 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -315,7 +315,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent, } int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent, - const struct bin_attribute *battr, umode_t mode, + const struct bin_attribute *battr, umode_t mode, size_t size, kuid_t uid, kgid_t gid, const void *ns) { const struct attribute *attr = &battr->attr; @@ -340,7 +340,7 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent, #endif kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid, - battr->size, ops, (void *)attr, ns, key); + size, ops, (void *)attr, ns, key); if (IS_ERR(kn)) { if (PTR_ERR(kn) == -EEXIST) sysfs_warn_dup(parent, attr->name); @@ -580,8 +580,8 @@ int sysfs_create_bin_file(struct kobject *kobj, return -EINVAL; kobject_get_ownership(kobj, &uid, &gid); - return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode, uid, - gid, NULL); + return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode, + attr->size, uid, gid, NULL); } EXPORT_SYMBOL_GPL(sysfs_create_bin_file); diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index d22ad67a0f32..45b2e92941da 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -87,6 +87,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, if (grp->bin_attrs) { for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) { umode_t mode = (*bin_attr)->attr.mode; + size_t size = (*bin_attr)->size; if (update) kernfs_remove_by_name(parent, @@ -104,7 +105,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, mode &= SYSFS_PREALLOC | 0664; error = sysfs_add_bin_file_mode_ns(parent, *bin_attr, - mode, uid, gid, + mode, size, uid, gid, NULL); if (error) break; diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3f28c9af5756..8e012f25e1c0 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h @@ -31,7 +31,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent, const struct attribute *attr, umode_t amode, kuid_t uid, kgid_t gid, const void *ns); int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent, - const struct bin_attribute *battr, umode_t mode, + const struct bin_attribute *battr, umode_t mode, size_t size, kuid_t uid, kgid_t gid, const void *ns); /* -- cgit v1.2.3 From bebf29b18f34620e25f7e2bd9e4e4d8e34a8977d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sun, 3 Nov 2024 17:03:31 +0000 Subject: sysfs: introduce callback attribute_group::bin_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several drivers need to dynamically calculate the size of an binary attribute. Currently this is done by assigning attr->size from the is_bin_visible() callback. This has drawbacks: * It is not documented. * A single attribute can be instantiated multiple times, overwriting the shared size field. * It prevents the structure to be moved to read-only memory. Introduce a new dedicated callback to calculate the size of the attribute. Signed-off-by: Thomas Weißschuh Acked-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20241103-sysfs-const-bin_attr-v2-2-71110628844c@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/group.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 45b2e92941da..8b01a7eda5fb 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -98,6 +98,8 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj, if (!mode) continue; } + if (grp->bin_size) + size = grp->bin_size(kobj, *bin_attr, i); WARN(mode & ~(SYSFS_PREALLOC | 0664), "Attribute %s: Invalid permissions 0%o\n", -- cgit v1.2.3 From eb2e6c3a8d66ff37b2ee26cd32334ae0e05fd596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sun, 3 Nov 2024 17:03:38 +0000 Subject: sysfs: bin_attribute: add const read/write callback variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Acked-by: Krzysztof Wilczyński Link: https://lore.kernel.org/r/20241103-sysfs-const-bin_attr-v2-9-71110628844c@weissschuh.net Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'fs') diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 6d39696b4306..785408861c01 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -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; -- cgit v1.2.3