^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * fs/sysfs/group.c - Operations for adding/removing multiple files at once.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2003 Patrick Mochel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (c) 2003 Open Source Development Lab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2013 Greg Kroah-Hartman
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2013 The Linux Foundation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "sysfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static void remove_files(struct kernfs_node *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct attribute *const *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct bin_attribute *const *bin_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (grp->attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) for (attr = grp->attrs; *attr; attr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) kernfs_remove_by_name(parent, (*attr)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if (grp->bin_attrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) kernfs_remove_by_name(parent, (*bin_attr)->attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int create_files(struct kernfs_node *parent, struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) kuid_t uid, kgid_t gid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const struct attribute_group *grp, int update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct attribute *const *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct bin_attribute *const *bin_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int error = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (grp->attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) for (i = 0, attr = grp->attrs; *attr && !error; i++, attr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) umode_t mode = (*attr)->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * In update mode, we're changing the permissions or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * visibility. Do this by first removing then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * re-adding (if required) the file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) kernfs_remove_by_name(parent, (*attr)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (grp->is_visible) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mode = grp->is_visible(kobj, *attr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) WARN(mode & ~(SYSFS_PREALLOC | 0664),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "Attribute %s: Invalid permissions 0%o\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) (*attr)->name, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) mode &= SYSFS_PREALLOC | 0664;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) error = sysfs_add_file_mode_ns(parent, *attr, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) mode, uid, gid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (unlikely(error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) remove_files(parent, grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (grp->bin_attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) umode_t mode = (*bin_attr)->attr.mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) kernfs_remove_by_name(parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) (*bin_attr)->attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (grp->is_bin_visible) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) mode = grp->is_bin_visible(kobj, *bin_attr, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (!mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) WARN(mode & ~(SYSFS_PREALLOC | 0664),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) "Attribute %s: Invalid permissions 0%o\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) (*bin_attr)->attr.name, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) mode &= SYSFS_PREALLOC | 0664;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) error = sysfs_add_file_mode_ns(parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) &(*bin_attr)->attr, true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) uid, gid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) remove_files(parent, grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static int internal_create_group(struct kobject *kobj, int update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (WARN_ON(!kobj || (!update && !kobj->sd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* Updates may happen before the object has been instantiated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (unlikely(update && !kobj->sd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!grp->attrs && !grp->bin_attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) WARN(1, "sysfs: (bin_)attrs not set by subsystem for group: %s/%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) kobj->name, grp->name ?: "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) kobject_get_ownership(kobj, &uid, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (grp->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) kn = kernfs_find_and_get(kobj->sd, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (!kn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) pr_warn("Can't update unknown attr grp name: %s/%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) kobj->name, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) kn = kernfs_create_dir_ns(kobj->sd, grp->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) S_IRWXU | S_IRUGO | S_IXUGO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) uid, gid, kobj, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (IS_ERR(kn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (PTR_ERR(kn) == -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) sysfs_warn_dup(kobj->sd, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return PTR_ERR(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) kn = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) kernfs_get(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) error = create_files(kn, kobj, uid, gid, grp, update);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if (grp->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) kernfs_remove(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (grp->name && update)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * sysfs_create_group - given a directory kobject, create an attribute group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @kobj: The kobject to create the group on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @grp: The attribute group to create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * This function creates a group for the first time. It will explicitly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * warn and error if any of the attribute files being created already exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int sysfs_create_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return internal_create_group(kobj, 0, grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) EXPORT_SYMBOL_GPL(sysfs_create_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static int internal_create_groups(struct kobject *kobj, int update,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) const struct attribute_group **groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) for (i = 0; groups[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) error = internal_create_group(kobj, update, groups[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) while (--i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) sysfs_remove_group(kobj, groups[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * sysfs_create_groups - given a directory kobject, create a bunch of attribute groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * @kobj: The kobject to create the group on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * @groups: The attribute groups to create, NULL terminated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) * This function creates a bunch of attribute groups. If an error occurs when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) * creating a group, all previously created groups will be removed, unwinding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) * everything back to the original state when this function was called.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * It will explicitly warn and error if any of the attribute files being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * created already exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * Returns 0 on success or error code from sysfs_create_group on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int sysfs_create_groups(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) const struct attribute_group **groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return internal_create_groups(kobj, 0, groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) EXPORT_SYMBOL_GPL(sysfs_create_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * sysfs_update_groups - given a directory kobject, create a bunch of attribute groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @kobj: The kobject to update the group on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @groups: The attribute groups to update, NULL terminated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * This function update a bunch of attribute groups. If an error occurs when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * updating a group, all previously updated groups will be removed together
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * with already existing (not updated) attributes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * Returns 0 on success or error code from sysfs_update_group on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int sysfs_update_groups(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) const struct attribute_group **groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return internal_create_groups(kobj, 1, groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) EXPORT_SYMBOL_GPL(sysfs_update_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * sysfs_update_group - given a directory kobject, update an attribute group
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * @kobj: The kobject to update the group on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * @grp: The attribute group to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * This function updates an attribute group. Unlike
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * sysfs_create_group(), it will explicitly not warn or error if any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * of the attribute files being created already exist. Furthermore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * if the visibility of the files has changed through the is_visible()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * callback, it will update the permissions and add or remove the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * relevant files. Changing a group's name (subdirectory name under
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * kobj's directory in sysfs) is not allowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * The primary use for this function is to call it after making a change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * that affects group visibility.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) int sysfs_update_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return internal_create_group(kobj, 1, grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) EXPORT_SYMBOL_GPL(sysfs_update_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * sysfs_remove_group: remove a group from a kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * @kobj: kobject to remove the group from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * @grp: group to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * This function removes a group of attributes from a kobject. The attributes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * previously have to have been created for this group, otherwise it will fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) void sysfs_remove_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct kernfs_node *parent = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (grp->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) kn = kernfs_find_and_get(parent, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (!kn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) WARN(!kn, KERN_WARNING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) "sysfs group '%s' not found for kobject '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) grp->name, kobject_name(kobj));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) kn = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) kernfs_get(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) remove_files(kn, grp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (grp->name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) kernfs_remove(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) EXPORT_SYMBOL_GPL(sysfs_remove_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * sysfs_remove_groups - remove a list of groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * @kobj: The kobject for the groups to be removed from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @groups: NULL terminated list of groups to be removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * If groups is not NULL, remove the specified groups from the kobject.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) void sysfs_remove_groups(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) const struct attribute_group **groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) for (i = 0; groups[i]; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) sysfs_remove_group(kobj, groups[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) EXPORT_SYMBOL_GPL(sysfs_remove_groups);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * sysfs_merge_group - merge files into a pre-existing attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * @grp: The files to create and the attribute group they belong to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * This function returns an error if the group doesn't exist or any of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * files already exist in that group, in which case none of the new files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * are created.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) int sysfs_merge_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) kuid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) kgid_t gid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct attribute *const *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) parent = kernfs_find_and_get(kobj->sd, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) kobject_get_ownership(kobj, &uid, &gid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) error = sysfs_add_file_mode_ns(parent, *attr, false,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) (*attr)->mode, uid, gid, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) while (--i >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) kernfs_remove_by_name(parent, (*--attr)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) EXPORT_SYMBOL_GPL(sysfs_merge_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * sysfs_unmerge_group - remove files from a pre-existing attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) * @grp: The files to remove and the attribute group they belong to.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) void sysfs_unmerge_group(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) const struct attribute_group *grp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) struct attribute *const *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) parent = kernfs_find_and_get(kobj->sd, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) for (attr = grp->attrs; *attr; ++attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) kernfs_remove_by_name(parent, (*attr)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) EXPORT_SYMBOL_GPL(sysfs_unmerge_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * sysfs_add_link_to_group - add a symlink to an attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * @group_name: The name of the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * @target: The target kobject of the symlink to create.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * @link_name: The name of the symlink to create.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int sysfs_add_link_to_group(struct kobject *kobj, const char *group_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct kobject *target, const char *link_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) parent = kernfs_find_and_get(kobj->sd, group_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) error = sysfs_create_link_sd(parent, target, link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) EXPORT_SYMBOL_GPL(sysfs_add_link_to_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * sysfs_remove_link_from_group - remove a symlink from an attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * @group_name: The name of the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * @link_name: The name of the symlink to remove.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) void sysfs_remove_link_from_group(struct kobject *kobj, const char *group_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) const char *link_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) struct kernfs_node *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) parent = kernfs_find_and_get(kobj->sd, group_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) if (parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) kernfs_remove_by_name(parent, link_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) kernfs_put(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) EXPORT_SYMBOL_GPL(sysfs_remove_link_from_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * compat_only_sysfs_link_entry_to_kobj - add a symlink to a kobject pointing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * to a group or an attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * @target_kobj: The target kobject.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * @target_name: The name of the target group or attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * @symlink_name: The name of the symlink file (target_name will be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * considered if symlink_name is NULL).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) struct kobject *target_kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) const char *target_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) const char *symlink_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) struct kernfs_node *target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) struct kernfs_node *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct kernfs_node *link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * We don't own @target_kobj and it may be removed at any time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * Synchronize using sysfs_symlink_target_lock. See sysfs_remove_dir()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) spin_lock(&sysfs_symlink_target_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) target = target_kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) kernfs_get(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) spin_unlock(&sysfs_symlink_target_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (!target)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) entry = kernfs_find_and_get(target_kobj->sd, target_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (!entry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) kernfs_put(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) if (!symlink_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) symlink_name = target_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) link = kernfs_create_link(kobj->sd, symlink_name, entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (PTR_ERR(link) == -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) sysfs_warn_dup(kobj->sd, symlink_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) kernfs_put(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) kernfs_put(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) return PTR_ERR_OR_ZERO(link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) const struct attribute_group *grp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) struct iattr *newattrs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) struct kernfs_node *kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (grp->attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) struct attribute *const *attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) for (attr = grp->attrs; *attr; attr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) kn = kernfs_find_and_get(grp_kn, (*attr)->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) error = kernfs_setattr(kn, newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (grp->bin_attrs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) struct bin_attribute *const *bin_attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if (!kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) error = kernfs_setattr(kn, newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) kernfs_put(kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * sysfs_group_change_owner - change owner of an attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * @kobj: The kobject containing the group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * @grp: The attribute group.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * @kuid: new owner's kuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * @kgid: new owner's kgid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) int sysfs_group_change_owner(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) const struct attribute_group *grp, kuid_t kuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct kernfs_node *grp_kn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct iattr newattrs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) .ia_valid = ATTR_UID | ATTR_GID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) .ia_uid = kuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) .ia_gid = kgid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) if (!kobj->state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (grp->name) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) grp_kn = kernfs_find_and_get(kobj->sd, grp->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) kernfs_get(kobj->sd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) grp_kn = kobj->sd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (!grp_kn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) error = kernfs_setattr(grp_kn, &newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (!error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) kernfs_put(grp_kn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) EXPORT_SYMBOL_GPL(sysfs_group_change_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * sysfs_groups_change_owner - change owner of a set of attribute groups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * @kobj: The kobject containing the groups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * @groups: The attribute groups.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * @kuid: new owner's kuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * @kgid: new owner's kgid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) * Returns 0 on success or error code on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) int sysfs_groups_change_owner(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) const struct attribute_group **groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) kuid_t kuid, kgid_t kgid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) int error = 0, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!kobj->state_in_sysfs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) if (!groups)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) for (i = 0; groups[i]; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) error = sysfs_group_change_owner(kobj, groups[i], kuid, kgid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) EXPORT_SYMBOL_GPL(sysfs_groups_change_owner);