Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);