if (grp->attrs) { for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
umode_t mode = (*attr)->mode;
/* * In update mode, we're changing the permissions or * visibility. Do this by first removing then * re-adding (if required) the file.
*/ if (update)
kernfs_remove_by_name(parent, (*attr)->name); if (grp->is_visible) {
mode = grp->is_visible(kobj, *attr, i);
mode &= ~SYSFS_GROUP_INVISIBLE; if (!mode) continue;
}
staticint internal_create_group(struct kobject *kobj, int update, conststruct attribute_group *grp)
{ struct kernfs_node *kn;
kuid_t uid;
kgid_t gid; int error;
if (WARN_ON(!kobj || (!update && !kobj->sd))) return -EINVAL;
/* Updates may happen before the object has been instantiated */ if (unlikely(update && !kobj->sd)) return -EINVAL;
if (!grp->attrs && !grp->bin_attrs) {
pr_debug("sysfs: (bin_)attrs not set by subsystem for group: %s/%s, skipping\n",
kobj->name, grp->name ?: ""); return 0;
}
if (update) {
kn = kernfs_find_and_get(kobj->sd, grp->name); if (!kn) {
pr_debug("attr grp %s/%s not created yet\n",
kobj->name, grp->name); /* may have been invisible prior to this update */
update = 0;
} elseif (!mode) {
sysfs_remove_group(kobj, grp);
kernfs_put(kn); return 0;
}
}
if (!update) { if (!mode) return 0;
kn = kernfs_create_dir_ns(kobj->sd, grp->name, mode,
uid, gid, kobj, NULL); if (IS_ERR(kn)) { if (PTR_ERR(kn) == -EEXIST)
sysfs_warn_dup(kobj->sd, grp->name); return PTR_ERR(kn);
}
}
} else {
kn = kobj->sd;
}
kernfs_get(kn);
error = create_files(kn, kobj, uid, gid, grp, update); if (error) { if (grp->name)
kernfs_remove(kn);
}
kernfs_put(kn);
if (grp->name && update)
kernfs_put(kn);
return error;
}
/** * sysfs_create_group - given a directory kobject, create an attribute group * @kobj: The kobject to create the group on * @grp: The attribute group to create * * This function creates a group for the first time. It will explicitly * warn and error if any of the attribute files being created already exist. * * Returns 0 on success or error code on failure.
*/ int sysfs_create_group(struct kobject *kobj, conststruct attribute_group *grp)
{ return internal_create_group(kobj, 0, grp);
}
EXPORT_SYMBOL_GPL(sysfs_create_group);
staticint internal_create_groups(struct kobject *kobj, int update, conststruct attribute_group **groups)
{ int error = 0; int i;
if (!groups) return 0;
for (i = 0; groups[i]; i++) {
error = internal_create_group(kobj, update, groups[i]); if (error) { while (--i >= 0)
sysfs_remove_group(kobj, groups[i]); break;
}
} return error;
}
/** * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups * @kobj: The kobject to create the group on * @groups: The attribute groups to create, NULL terminated * * This function creates a bunch of attribute groups. If an error occurs when * creating a group, all previously created groups will be removed, unwinding * everything back to the original state when this function was called. * It will explicitly warn and error if any of the attribute files being * created already exist. * * Returns 0 on success or error code from sysfs_create_group on failure.
*/ int sysfs_create_groups(struct kobject *kobj, conststruct attribute_group **groups)
{ return internal_create_groups(kobj, 0, groups);
}
EXPORT_SYMBOL_GPL(sysfs_create_groups);
/** * sysfs_update_groups - given a directory kobject, create a bunch of attribute groups * @kobj: The kobject to update the group on * @groups: The attribute groups to update, NULL terminated * * This function update a bunch of attribute groups. If an error occurs when * updating a group, all previously updated groups will be removed together * with already existing (not updated) attributes. * * Returns 0 on success or error code from sysfs_update_group on failure.
*/ int sysfs_update_groups(struct kobject *kobj, conststruct attribute_group **groups)
{ return internal_create_groups(kobj, 1, groups);
}
EXPORT_SYMBOL_GPL(sysfs_update_groups);
/** * sysfs_update_group - given a directory kobject, update an attribute group * @kobj: The kobject to update the group on * @grp: The attribute group to update * * This function updates an attribute group. Unlike * sysfs_create_group(), it will explicitly not warn or error if any * of the attribute files being created already exist. Furthermore, * if the visibility of the files has changed through the is_visible() * callback, it will update the permissions and add or remove the * relevant files. Changing a group's name (subdirectory name under * kobj's directory in sysfs) is not allowed. * * The primary use for this function is to call it after making a change * that affects group visibility. * * Returns 0 on success or error code on failure.
*/ int sysfs_update_group(struct kobject *kobj, conststruct attribute_group *grp)
{ return internal_create_group(kobj, 1, grp);
}
EXPORT_SYMBOL_GPL(sysfs_update_group);
/** * sysfs_remove_group: remove a group from a kobject * @kobj: kobject to remove the group from * @grp: group to remove * * This function removes a group of attributes from a kobject. The attributes * previously have to have been created for this group, otherwise it will fail.
*/ void sysfs_remove_group(struct kobject *kobj, conststruct attribute_group *grp)
{ struct kernfs_node *parent = kobj->sd; struct kernfs_node *kn;
if (grp->name) {
kn = kernfs_find_and_get(parent, grp->name); if (!kn) {
pr_debug("sysfs group '%s' not found for kobject '%s'\n",
grp->name, kobject_name(kobj)); return;
}
} else {
kn = parent;
kernfs_get(kn);
}
remove_files(kn, grp); if (grp->name)
kernfs_remove(kn);
/** * sysfs_remove_groups - remove a list of groups * * @kobj: The kobject for the groups to be removed from * @groups: NULL terminated list of groups to be removed * * If groups is not NULL, remove the specified groups from the kobject.
*/ void sysfs_remove_groups(struct kobject *kobj, conststruct attribute_group **groups)
{ int i;
if (!groups) return; for (i = 0; groups[i]; i++)
sysfs_remove_group(kobj, groups[i]);
}
EXPORT_SYMBOL_GPL(sysfs_remove_groups);
/** * sysfs_merge_group - merge files into a pre-existing named attribute group. * @kobj: The kobject containing the group. * @grp: The files to create and the attribute group they belong to. * * This function returns an error if the group doesn't exist, the .name field is * NULL or any of the files already exist in that group, in which case none of * the new files are created.
*/ int sysfs_merge_group(struct kobject *kobj, conststruct attribute_group *grp)
{ struct kernfs_node *parent;
kuid_t uid;
kgid_t gid; int error = 0; struct attribute *const *attr; int i;
parent = kernfs_find_and_get(kobj->sd, grp->name); if (!parent) return -ENOENT;
/** * sysfs_unmerge_group - remove files from a pre-existing named attribute group. * @kobj: The kobject containing the group. * @grp: The files to remove and the attribute group they belong to.
*/ void sysfs_unmerge_group(struct kobject *kobj, conststruct attribute_group *grp)
{ struct kernfs_node *parent; struct attribute *const *attr;
parent = kernfs_find_and_get(kobj->sd, grp->name); if (parent) { for (attr = grp->attrs; *attr; ++attr)
kernfs_remove_by_name(parent, (*attr)->name);
kernfs_put(parent);
}
}
EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
/** * sysfs_add_link_to_group - add a symlink to an attribute group. * @kobj: The kobject containing the group. * @group_name: The name of the group. * @target: The target kobject of the symlink to create. * @link_name: The name of the symlink to create.
*/ int sysfs_add_link_to_group(struct kobject *kobj, constchar *group_name, struct kobject *target, constchar *link_name)
{ struct kernfs_node *parent; int error = 0;
parent = kernfs_find_and_get(kobj->sd, group_name); if (!parent) return -ENOENT;
/** * sysfs_remove_link_from_group - remove a symlink from an attribute group. * @kobj: The kobject containing the group. * @group_name: The name of the group. * @link_name: The name of the symlink to remove.
*/ void sysfs_remove_link_from_group(struct kobject *kobj, constchar *group_name, constchar *link_name)
{ struct kernfs_node *parent;
/** * compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing * to a group or an attribute * @kobj: The kobject containing the group. * @target_kobj: The target kobject. * @target_name: The name of the target group or attribute. * @symlink_name: The name of the symlink file (target_name will be * considered if symlink_name is NULL).
*/ int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, struct kobject *target_kobj, constchar *target_name, constchar *symlink_name)
{ struct kernfs_node *target; struct kernfs_node *entry; struct kernfs_node *link;
/* * We don't own @target_kobj and it may be removed at any time. * Synchronize using sysfs_symlink_target_lock. See sysfs_remove_dir() * for details.
*/
spin_lock(&sysfs_symlink_target_lock);
target = target_kobj->sd; if (target)
kernfs_get(target);
spin_unlock(&sysfs_symlink_target_lock); if (!target) return -ENOENT;
/** * sysfs_groups_change_owner - change owner of a set of attribute groups. * @kobj: The kobject containing the groups. * @groups: The attribute groups. * @kuid: new owner's kuid * @kgid: new owner's kgid * * Returns 0 on success or error code on failure.
*/ int sysfs_groups_change_owner(struct kobject *kobj, conststruct attribute_group **groups,
kuid_t kuid, kgid_t kgid)
{ int error = 0, i;
if (!kobj->state_in_sysfs) return -EINVAL;
if (!groups) return 0;
for (i = 0; groups[i]; i++) {
error = sysfs_group_change_owner(kobj, groups[i], kuid, kgid); if (error) break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.