sysfs: split out binary attribute handling from sysfs_add_file_mode_ns

Split adding binary attributes into a separate handler instead of
overloading sysfs_add_file_mode_ns.

Acked-by: Christian Brauner <christian.brauner@ubuntu.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20210913054121.616001-5-hch@lst.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Christoph Hellwig 2021-09-13 07:41:12 +02:00 committed by Greg Kroah-Hartman
parent eaf501e0d8
commit 5cf3bb0d3a
3 changed files with 78 additions and 65 deletions

View file

@ -255,59 +255,38 @@ static const struct kernfs_ops sysfs_bin_kfops_mmap = {
}; };
int sysfs_add_file_mode_ns(struct kernfs_node *parent, int sysfs_add_file_mode_ns(struct kernfs_node *parent,
const struct attribute *attr, bool is_bin, const struct attribute *attr, umode_t mode, kuid_t uid,
umode_t mode, kuid_t uid, kgid_t gid, const void *ns) kgid_t gid, const void *ns)
{ {
struct kobject *kobj = parent->priv;
const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops;
struct lock_class_key *key = NULL; struct lock_class_key *key = NULL;
const struct kernfs_ops *ops; const struct kernfs_ops *ops;
struct kernfs_node *kn; struct kernfs_node *kn;
loff_t size;
if (!is_bin) { /* every kobject with an attribute needs a ktype assigned */
struct kobject *kobj = parent->priv; if (WARN(!sysfs_ops, KERN_ERR
const struct sysfs_ops *sysfs_ops = kobj->ktype->sysfs_ops; "missing sysfs attribute operations for kobject: %s\n",
kobject_name(kobj)))
return -EINVAL;
/* every kobject with an attribute needs a ktype assigned */ if (sysfs_ops->show && sysfs_ops->store) {
if (WARN(!sysfs_ops, KERN_ERR if (mode & SYSFS_PREALLOC)
"missing sysfs attribute operations for kobject: %s\n", ops = &sysfs_prealloc_kfops_rw;
kobject_name(kobj)))
return -EINVAL;
if (sysfs_ops->show && sysfs_ops->store) {
if (mode & SYSFS_PREALLOC)
ops = &sysfs_prealloc_kfops_rw;
else
ops = &sysfs_file_kfops_rw;
} else if (sysfs_ops->show) {
if (mode & SYSFS_PREALLOC)
ops = &sysfs_prealloc_kfops_ro;
else
ops = &sysfs_file_kfops_ro;
} else if (sysfs_ops->store) {
if (mode & SYSFS_PREALLOC)
ops = &sysfs_prealloc_kfops_wo;
else
ops = &sysfs_file_kfops_wo;
} else
ops = &sysfs_file_kfops_empty;
size = PAGE_SIZE;
} else {
struct bin_attribute *battr = (void *)attr;
if (battr->mmap)
ops = &sysfs_bin_kfops_mmap;
else if (battr->read && battr->write)
ops = &sysfs_bin_kfops_rw;
else if (battr->read)
ops = &sysfs_bin_kfops_ro;
else if (battr->write)
ops = &sysfs_bin_kfops_wo;
else else
ops = &sysfs_file_kfops_empty; ops = &sysfs_file_kfops_rw;
} else if (sysfs_ops->show) {
size = battr->size; if (mode & SYSFS_PREALLOC)
} ops = &sysfs_prealloc_kfops_ro;
else
ops = &sysfs_file_kfops_ro;
} else if (sysfs_ops->store) {
if (mode & SYSFS_PREALLOC)
ops = &sysfs_prealloc_kfops_wo;
else
ops = &sysfs_file_kfops_wo;
} else
ops = &sysfs_file_kfops_empty;
#ifdef CONFIG_DEBUG_LOCK_ALLOC #ifdef CONFIG_DEBUG_LOCK_ALLOC
if (!attr->ignore_lockdep) if (!attr->ignore_lockdep)
@ -315,7 +294,42 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
#endif #endif
kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid, kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
size, ops, (void *)attr, ns, key); PAGE_SIZE, ops, (void *)attr, ns, key);
if (IS_ERR(kn)) {
if (PTR_ERR(kn) == -EEXIST)
sysfs_warn_dup(parent, attr->name);
return PTR_ERR(kn);
}
return 0;
}
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct bin_attribute *battr, umode_t mode,
kuid_t uid, kgid_t gid, const void *ns)
{
const struct attribute *attr = &battr->attr;
struct lock_class_key *key = NULL;
const struct kernfs_ops *ops;
struct kernfs_node *kn;
if (battr->mmap)
ops = &sysfs_bin_kfops_mmap;
else if (battr->read && battr->write)
ops = &sysfs_bin_kfops_rw;
else if (battr->read)
ops = &sysfs_bin_kfops_ro;
else if (battr->write)
ops = &sysfs_bin_kfops_wo;
else
ops = &sysfs_file_kfops_empty;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
if (!attr->ignore_lockdep)
key = attr->key ?: (struct lock_class_key *)&attr->skey;
#endif
kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
battr->size, ops, (void *)attr, ns, key);
if (IS_ERR(kn)) { if (IS_ERR(kn)) {
if (PTR_ERR(kn) == -EEXIST) if (PTR_ERR(kn) == -EEXIST)
sysfs_warn_dup(parent, attr->name); sysfs_warn_dup(parent, attr->name);
@ -340,9 +354,7 @@ int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
return -EINVAL; return -EINVAL;
kobject_get_ownership(kobj, &uid, &gid); kobject_get_ownership(kobj, &uid, &gid);
return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode, return sysfs_add_file_mode_ns(kobj->sd, attr, attr->mode, uid, gid, ns);
uid, gid, ns);
} }
EXPORT_SYMBOL_GPL(sysfs_create_file_ns); EXPORT_SYMBOL_GPL(sysfs_create_file_ns);
@ -385,8 +397,8 @@ int sysfs_add_file_to_group(struct kobject *kobj,
return -ENOENT; return -ENOENT;
kobject_get_ownership(kobj, &uid, &gid); kobject_get_ownership(kobj, &uid, &gid);
error = sysfs_add_file_mode_ns(parent, attr, false, error = sysfs_add_file_mode_ns(parent, attr, attr->mode, uid, gid,
attr->mode, uid, gid, NULL); NULL);
kernfs_put(parent); kernfs_put(parent);
return error; return error;
@ -555,8 +567,8 @@ int sysfs_create_bin_file(struct kobject *kobj,
return -EINVAL; return -EINVAL;
kobject_get_ownership(kobj, &uid, &gid); kobject_get_ownership(kobj, &uid, &gid);
return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true, return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode, uid,
attr->attr.mode, uid, gid, NULL); gid, NULL);
} }
EXPORT_SYMBOL_GPL(sysfs_create_bin_file); EXPORT_SYMBOL_GPL(sysfs_create_bin_file);

View file

@ -61,8 +61,8 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
(*attr)->name, mode); (*attr)->name, mode);
mode &= SYSFS_PREALLOC | 0664; mode &= SYSFS_PREALLOC | 0664;
error = sysfs_add_file_mode_ns(parent, *attr, false, error = sysfs_add_file_mode_ns(parent, *attr, mode, uid,
mode, uid, gid, NULL); gid, NULL);
if (unlikely(error)) if (unlikely(error))
break; break;
} }
@ -90,10 +90,9 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
(*bin_attr)->attr.name, mode); (*bin_attr)->attr.name, mode);
mode &= SYSFS_PREALLOC | 0664; mode &= SYSFS_PREALLOC | 0664;
error = sysfs_add_file_mode_ns(parent, error = sysfs_add_bin_file_mode_ns(parent, *bin_attr,
&(*bin_attr)->attr, true, mode, uid, gid,
mode, NULL);
uid, gid, NULL);
if (error) if (error)
break; break;
} }
@ -340,8 +339,8 @@ int sysfs_merge_group(struct kobject *kobj,
kobject_get_ownership(kobj, &uid, &gid); kobject_get_ownership(kobj, &uid, &gid);
for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr)) for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
error = sysfs_add_file_mode_ns(parent, *attr, false, error = sysfs_add_file_mode_ns(parent, *attr, (*attr)->mode,
(*attr)->mode, uid, gid, NULL); uid, gid, NULL);
if (error) { if (error) {
while (--i >= 0) while (--i >= 0)
kernfs_remove_by_name(parent, (*--attr)->name); kernfs_remove_by_name(parent, (*--attr)->name);

View file

@ -28,9 +28,11 @@ void sysfs_warn_dup(struct kernfs_node *parent, const char *name);
* file.c * file.c
*/ */
int sysfs_add_file_mode_ns(struct kernfs_node *parent, int sysfs_add_file_mode_ns(struct kernfs_node *parent,
const struct attribute *attr, bool is_bin, const struct attribute *attr, umode_t amode, kuid_t uid,
umode_t amode, kuid_t uid, kgid_t gid, kgid_t gid, const void *ns);
const void *ns); int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct bin_attribute *battr, umode_t mode,
kuid_t uid, kgid_t gid, const void *ns);
/* /*
* symlink.c * symlink.c