162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * kobject.c - library routines for handling generic kernel objects
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
662306a36Sopenharmony_ci * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com>
762306a36Sopenharmony_ci * Copyright (c) 2006-2007 Novell Inc.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Please see the file Documentation/core-api/kobject.rst for critical information
1062306a36Sopenharmony_ci * about using the kobject interface.
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/kobject.h>
1662306a36Sopenharmony_ci#include <linux/string.h>
1762306a36Sopenharmony_ci#include <linux/export.h>
1862306a36Sopenharmony_ci#include <linux/stat.h>
1962306a36Sopenharmony_ci#include <linux/slab.h>
2062306a36Sopenharmony_ci#include <linux/random.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/**
2362306a36Sopenharmony_ci * kobject_namespace() - Return @kobj's namespace tag.
2462306a36Sopenharmony_ci * @kobj: kobject in question
2562306a36Sopenharmony_ci *
2662306a36Sopenharmony_ci * Returns namespace tag of @kobj if its parent has namespace ops enabled
2762306a36Sopenharmony_ci * and thus @kobj should have a namespace tag associated with it.  Returns
2862306a36Sopenharmony_ci * %NULL otherwise.
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ciconst void *kobject_namespace(const struct kobject *kobj)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE)
3562306a36Sopenharmony_ci		return NULL;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	return kobj->ktype->namespace(kobj);
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/**
4162306a36Sopenharmony_ci * kobject_get_ownership() - Get sysfs ownership data for @kobj.
4262306a36Sopenharmony_ci * @kobj: kobject in question
4362306a36Sopenharmony_ci * @uid: kernel user ID for sysfs objects
4462306a36Sopenharmony_ci * @gid: kernel group ID for sysfs objects
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * Returns initial uid/gid pair that should be used when creating sysfs
4762306a36Sopenharmony_ci * representation of given kobject. Normally used to adjust ownership of
4862306a36Sopenharmony_ci * objects in a container.
4962306a36Sopenharmony_ci */
5062306a36Sopenharmony_civoid kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	*uid = GLOBAL_ROOT_UID;
5362306a36Sopenharmony_ci	*gid = GLOBAL_ROOT_GID;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (kobj->ktype->get_ownership)
5662306a36Sopenharmony_ci		kobj->ktype->get_ownership(kobj, uid, gid);
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistatic bool kobj_ns_type_is_valid(enum kobj_ns_type type)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	if ((type <= KOBJ_NS_TYPE_NONE) || (type >= KOBJ_NS_TYPES))
6262306a36Sopenharmony_ci		return false;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	return true;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic int create_dir(struct kobject *kobj)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	const struct kobj_type *ktype = get_ktype(kobj);
7062306a36Sopenharmony_ci	const struct kobj_ns_type_operations *ops;
7162306a36Sopenharmony_ci	int error;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
7462306a36Sopenharmony_ci	if (error)
7562306a36Sopenharmony_ci		return error;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (ktype) {
7862306a36Sopenharmony_ci		error = sysfs_create_groups(kobj, ktype->default_groups);
7962306a36Sopenharmony_ci		if (error) {
8062306a36Sopenharmony_ci			sysfs_remove_dir(kobj);
8162306a36Sopenharmony_ci			return error;
8262306a36Sopenharmony_ci		}
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	/*
8662306a36Sopenharmony_ci	 * @kobj->sd may be deleted by an ancestor going away.  Hold an
8762306a36Sopenharmony_ci	 * extra reference so that it stays until @kobj is gone.
8862306a36Sopenharmony_ci	 */
8962306a36Sopenharmony_ci	sysfs_get(kobj->sd);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	/*
9262306a36Sopenharmony_ci	 * If @kobj has ns_ops, its children need to be filtered based on
9362306a36Sopenharmony_ci	 * their namespace tags.  Enable namespace support on @kobj->sd.
9462306a36Sopenharmony_ci	 */
9562306a36Sopenharmony_ci	ops = kobj_child_ns_ops(kobj);
9662306a36Sopenharmony_ci	if (ops) {
9762306a36Sopenharmony_ci		BUG_ON(!kobj_ns_type_is_valid(ops->type));
9862306a36Sopenharmony_ci		BUG_ON(!kobj_ns_type_registered(ops->type));
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci		sysfs_enable_ns(kobj->sd);
10162306a36Sopenharmony_ci	}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	return 0;
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int get_kobj_path_length(const struct kobject *kobj)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	int length = 1;
10962306a36Sopenharmony_ci	const struct kobject *parent = kobj;
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	/* walk up the ancestors until we hit the one pointing to the
11262306a36Sopenharmony_ci	 * root.
11362306a36Sopenharmony_ci	 * Add 1 to strlen for leading '/' of each level.
11462306a36Sopenharmony_ci	 */
11562306a36Sopenharmony_ci	do {
11662306a36Sopenharmony_ci		if (kobject_name(parent) == NULL)
11762306a36Sopenharmony_ci			return 0;
11862306a36Sopenharmony_ci		length += strlen(kobject_name(parent)) + 1;
11962306a36Sopenharmony_ci		parent = parent->parent;
12062306a36Sopenharmony_ci	} while (parent);
12162306a36Sopenharmony_ci	return length;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic int fill_kobj_path(const struct kobject *kobj, char *path, int length)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	const struct kobject *parent;
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	--length;
12962306a36Sopenharmony_ci	for (parent = kobj; parent; parent = parent->parent) {
13062306a36Sopenharmony_ci		int cur = strlen(kobject_name(parent));
13162306a36Sopenharmony_ci		/* back up enough to print this name with '/' */
13262306a36Sopenharmony_ci		length -= cur;
13362306a36Sopenharmony_ci		if (length <= 0)
13462306a36Sopenharmony_ci			return -EINVAL;
13562306a36Sopenharmony_ci		memcpy(path + length, kobject_name(parent), cur);
13662306a36Sopenharmony_ci		*(path + --length) = '/';
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	pr_debug("'%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
14062306a36Sopenharmony_ci		 kobj, __func__, path);
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_ci	return 0;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/**
14662306a36Sopenharmony_ci * kobject_get_path() - Allocate memory and fill in the path for @kobj.
14762306a36Sopenharmony_ci * @kobj:	kobject in question, with which to build the path
14862306a36Sopenharmony_ci * @gfp_mask:	the allocation type used to allocate the path
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci * Return: The newly allocated memory, caller must free with kfree().
15162306a36Sopenharmony_ci */
15262306a36Sopenharmony_cichar *kobject_get_path(const struct kobject *kobj, gfp_t gfp_mask)
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	char *path;
15562306a36Sopenharmony_ci	int len;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciretry:
15862306a36Sopenharmony_ci	len = get_kobj_path_length(kobj);
15962306a36Sopenharmony_ci	if (len == 0)
16062306a36Sopenharmony_ci		return NULL;
16162306a36Sopenharmony_ci	path = kzalloc(len, gfp_mask);
16262306a36Sopenharmony_ci	if (!path)
16362306a36Sopenharmony_ci		return NULL;
16462306a36Sopenharmony_ci	if (fill_kobj_path(kobj, path, len)) {
16562306a36Sopenharmony_ci		kfree(path);
16662306a36Sopenharmony_ci		goto retry;
16762306a36Sopenharmony_ci	}
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	return path;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobject_get_path);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci/* add the kobject to its kset's list */
17462306a36Sopenharmony_cistatic void kobj_kset_join(struct kobject *kobj)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	if (!kobj->kset)
17762306a36Sopenharmony_ci		return;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	kset_get(kobj->kset);
18062306a36Sopenharmony_ci	spin_lock(&kobj->kset->list_lock);
18162306a36Sopenharmony_ci	list_add_tail(&kobj->entry, &kobj->kset->list);
18262306a36Sopenharmony_ci	spin_unlock(&kobj->kset->list_lock);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* remove the kobject from its kset's list */
18662306a36Sopenharmony_cistatic void kobj_kset_leave(struct kobject *kobj)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	if (!kobj->kset)
18962306a36Sopenharmony_ci		return;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	spin_lock(&kobj->kset->list_lock);
19262306a36Sopenharmony_ci	list_del_init(&kobj->entry);
19362306a36Sopenharmony_ci	spin_unlock(&kobj->kset->list_lock);
19462306a36Sopenharmony_ci	kset_put(kobj->kset);
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic void kobject_init_internal(struct kobject *kobj)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	if (!kobj)
20062306a36Sopenharmony_ci		return;
20162306a36Sopenharmony_ci	kref_init(&kobj->kref);
20262306a36Sopenharmony_ci	INIT_LIST_HEAD(&kobj->entry);
20362306a36Sopenharmony_ci	kobj->state_in_sysfs = 0;
20462306a36Sopenharmony_ci	kobj->state_add_uevent_sent = 0;
20562306a36Sopenharmony_ci	kobj->state_remove_uevent_sent = 0;
20662306a36Sopenharmony_ci	kobj->state_initialized = 1;
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_cistatic int kobject_add_internal(struct kobject *kobj)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	int error = 0;
21362306a36Sopenharmony_ci	struct kobject *parent;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	if (!kobj)
21662306a36Sopenharmony_ci		return -ENOENT;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (!kobj->name || !kobj->name[0]) {
21962306a36Sopenharmony_ci		WARN(1,
22062306a36Sopenharmony_ci		     "kobject: (%p): attempted to be registered with empty name!\n",
22162306a36Sopenharmony_ci		     kobj);
22262306a36Sopenharmony_ci		return -EINVAL;
22362306a36Sopenharmony_ci	}
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	parent = kobject_get(kobj->parent);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	/* join kset if set, use it as parent if we do not already have one */
22862306a36Sopenharmony_ci	if (kobj->kset) {
22962306a36Sopenharmony_ci		if (!parent)
23062306a36Sopenharmony_ci			parent = kobject_get(&kobj->kset->kobj);
23162306a36Sopenharmony_ci		kobj_kset_join(kobj);
23262306a36Sopenharmony_ci		kobj->parent = parent;
23362306a36Sopenharmony_ci	}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	pr_debug("'%s' (%p): %s: parent: '%s', set: '%s'\n",
23662306a36Sopenharmony_ci		 kobject_name(kobj), kobj, __func__,
23762306a36Sopenharmony_ci		 parent ? kobject_name(parent) : "<NULL>",
23862306a36Sopenharmony_ci		 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	error = create_dir(kobj);
24162306a36Sopenharmony_ci	if (error) {
24262306a36Sopenharmony_ci		kobj_kset_leave(kobj);
24362306a36Sopenharmony_ci		kobject_put(parent);
24462306a36Sopenharmony_ci		kobj->parent = NULL;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci		/* be noisy on error issues */
24762306a36Sopenharmony_ci		if (error == -EEXIST)
24862306a36Sopenharmony_ci			pr_err("%s failed for %s with -EEXIST, don't try to register things with the same name in the same directory.\n",
24962306a36Sopenharmony_ci			       __func__, kobject_name(kobj));
25062306a36Sopenharmony_ci		else
25162306a36Sopenharmony_ci			pr_err("%s failed for %s (error: %d parent: %s)\n",
25262306a36Sopenharmony_ci			       __func__, kobject_name(kobj), error,
25362306a36Sopenharmony_ci			       parent ? kobject_name(parent) : "'none'");
25462306a36Sopenharmony_ci	} else
25562306a36Sopenharmony_ci		kobj->state_in_sysfs = 1;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	return error;
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci/**
26162306a36Sopenharmony_ci * kobject_set_name_vargs() - Set the name of a kobject.
26262306a36Sopenharmony_ci * @kobj: struct kobject to set the name of
26362306a36Sopenharmony_ci * @fmt: format string used to build the name
26462306a36Sopenharmony_ci * @vargs: vargs to format the string.
26562306a36Sopenharmony_ci */
26662306a36Sopenharmony_ciint kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
26762306a36Sopenharmony_ci				  va_list vargs)
26862306a36Sopenharmony_ci{
26962306a36Sopenharmony_ci	const char *s;
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_ci	if (kobj->name && !fmt)
27262306a36Sopenharmony_ci		return 0;
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	s = kvasprintf_const(GFP_KERNEL, fmt, vargs);
27562306a36Sopenharmony_ci	if (!s)
27662306a36Sopenharmony_ci		return -ENOMEM;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	/*
27962306a36Sopenharmony_ci	 * ewww... some of these buggers have '/' in the name ... If
28062306a36Sopenharmony_ci	 * that's the case, we need to make sure we have an actual
28162306a36Sopenharmony_ci	 * allocated copy to modify, since kvasprintf_const may have
28262306a36Sopenharmony_ci	 * returned something from .rodata.
28362306a36Sopenharmony_ci	 */
28462306a36Sopenharmony_ci	if (strchr(s, '/')) {
28562306a36Sopenharmony_ci		char *t;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		t = kstrdup(s, GFP_KERNEL);
28862306a36Sopenharmony_ci		kfree_const(s);
28962306a36Sopenharmony_ci		if (!t)
29062306a36Sopenharmony_ci			return -ENOMEM;
29162306a36Sopenharmony_ci		s = strreplace(t, '/', '!');
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci	kfree_const(kobj->name);
29462306a36Sopenharmony_ci	kobj->name = s;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return 0;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/**
30062306a36Sopenharmony_ci * kobject_set_name() - Set the name of a kobject.
30162306a36Sopenharmony_ci * @kobj: struct kobject to set the name of
30262306a36Sopenharmony_ci * @fmt: format string used to build the name
30362306a36Sopenharmony_ci *
30462306a36Sopenharmony_ci * This sets the name of the kobject.  If you have already added the
30562306a36Sopenharmony_ci * kobject to the system, you must call kobject_rename() in order to
30662306a36Sopenharmony_ci * change the name of the kobject.
30762306a36Sopenharmony_ci */
30862306a36Sopenharmony_ciint kobject_set_name(struct kobject *kobj, const char *fmt, ...)
30962306a36Sopenharmony_ci{
31062306a36Sopenharmony_ci	va_list vargs;
31162306a36Sopenharmony_ci	int retval;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci	va_start(vargs, fmt);
31462306a36Sopenharmony_ci	retval = kobject_set_name_vargs(kobj, fmt, vargs);
31562306a36Sopenharmony_ci	va_end(vargs);
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	return retval;
31862306a36Sopenharmony_ci}
31962306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_set_name);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/**
32262306a36Sopenharmony_ci * kobject_init() - Initialize a kobject structure.
32362306a36Sopenharmony_ci * @kobj: pointer to the kobject to initialize
32462306a36Sopenharmony_ci * @ktype: pointer to the ktype for this kobject.
32562306a36Sopenharmony_ci *
32662306a36Sopenharmony_ci * This function will properly initialize a kobject such that it can then
32762306a36Sopenharmony_ci * be passed to the kobject_add() call.
32862306a36Sopenharmony_ci *
32962306a36Sopenharmony_ci * After this function is called, the kobject MUST be cleaned up by a call
33062306a36Sopenharmony_ci * to kobject_put(), not by a call to kfree directly to ensure that all of
33162306a36Sopenharmony_ci * the memory is cleaned up properly.
33262306a36Sopenharmony_ci */
33362306a36Sopenharmony_civoid kobject_init(struct kobject *kobj, const struct kobj_type *ktype)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	char *err_str;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	if (!kobj) {
33862306a36Sopenharmony_ci		err_str = "invalid kobject pointer!";
33962306a36Sopenharmony_ci		goto error;
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci	if (!ktype) {
34262306a36Sopenharmony_ci		err_str = "must have a ktype to be initialized properly!\n";
34362306a36Sopenharmony_ci		goto error;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci	if (kobj->state_initialized) {
34662306a36Sopenharmony_ci		/* do not error out as sometimes we can recover */
34762306a36Sopenharmony_ci		pr_err("kobject (%p): tried to init an initialized object, something is seriously wrong.\n",
34862306a36Sopenharmony_ci		       kobj);
34962306a36Sopenharmony_ci		dump_stack_lvl(KERN_ERR);
35062306a36Sopenharmony_ci	}
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	kobject_init_internal(kobj);
35362306a36Sopenharmony_ci	kobj->ktype = ktype;
35462306a36Sopenharmony_ci	return;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_cierror:
35762306a36Sopenharmony_ci	pr_err("kobject (%p): %s\n", kobj, err_str);
35862306a36Sopenharmony_ci	dump_stack_lvl(KERN_ERR);
35962306a36Sopenharmony_ci}
36062306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_init);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic __printf(3, 0) int kobject_add_varg(struct kobject *kobj,
36362306a36Sopenharmony_ci					   struct kobject *parent,
36462306a36Sopenharmony_ci					   const char *fmt, va_list vargs)
36562306a36Sopenharmony_ci{
36662306a36Sopenharmony_ci	int retval;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	retval = kobject_set_name_vargs(kobj, fmt, vargs);
36962306a36Sopenharmony_ci	if (retval) {
37062306a36Sopenharmony_ci		pr_err("can not set name properly!\n");
37162306a36Sopenharmony_ci		return retval;
37262306a36Sopenharmony_ci	}
37362306a36Sopenharmony_ci	kobj->parent = parent;
37462306a36Sopenharmony_ci	return kobject_add_internal(kobj);
37562306a36Sopenharmony_ci}
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci/**
37862306a36Sopenharmony_ci * kobject_add() - The main kobject add function.
37962306a36Sopenharmony_ci * @kobj: the kobject to add
38062306a36Sopenharmony_ci * @parent: pointer to the parent of the kobject.
38162306a36Sopenharmony_ci * @fmt: format to name the kobject with.
38262306a36Sopenharmony_ci *
38362306a36Sopenharmony_ci * The kobject name is set and added to the kobject hierarchy in this
38462306a36Sopenharmony_ci * function.
38562306a36Sopenharmony_ci *
38662306a36Sopenharmony_ci * If @parent is set, then the parent of the @kobj will be set to it.
38762306a36Sopenharmony_ci * If @parent is NULL, then the parent of the @kobj will be set to the
38862306a36Sopenharmony_ci * kobject associated with the kset assigned to this kobject.  If no kset
38962306a36Sopenharmony_ci * is assigned to the kobject, then the kobject will be located in the
39062306a36Sopenharmony_ci * root of the sysfs tree.
39162306a36Sopenharmony_ci *
39262306a36Sopenharmony_ci * Note, no "add" uevent will be created with this call, the caller should set
39362306a36Sopenharmony_ci * up all of the necessary sysfs files for the object and then call
39462306a36Sopenharmony_ci * kobject_uevent() with the UEVENT_ADD parameter to ensure that
39562306a36Sopenharmony_ci * userspace is properly notified of this kobject's creation.
39662306a36Sopenharmony_ci *
39762306a36Sopenharmony_ci * Return: If this function returns an error, kobject_put() must be
39862306a36Sopenharmony_ci *         called to properly clean up the memory associated with the
39962306a36Sopenharmony_ci *         object.  Under no instance should the kobject that is passed
40062306a36Sopenharmony_ci *         to this function be directly freed with a call to kfree(),
40162306a36Sopenharmony_ci *         that can leak memory.
40262306a36Sopenharmony_ci *
40362306a36Sopenharmony_ci *         If this function returns success, kobject_put() must also be called
40462306a36Sopenharmony_ci *         in order to properly clean up the memory associated with the object.
40562306a36Sopenharmony_ci *
40662306a36Sopenharmony_ci *         In short, once this function is called, kobject_put() MUST be called
40762306a36Sopenharmony_ci *         when the use of the object is finished in order to properly free
40862306a36Sopenharmony_ci *         everything.
40962306a36Sopenharmony_ci */
41062306a36Sopenharmony_ciint kobject_add(struct kobject *kobj, struct kobject *parent,
41162306a36Sopenharmony_ci		const char *fmt, ...)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	va_list args;
41462306a36Sopenharmony_ci	int retval;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if (!kobj)
41762306a36Sopenharmony_ci		return -EINVAL;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (!kobj->state_initialized) {
42062306a36Sopenharmony_ci		pr_err("kobject '%s' (%p): tried to add an uninitialized object, something is seriously wrong.\n",
42162306a36Sopenharmony_ci		       kobject_name(kobj), kobj);
42262306a36Sopenharmony_ci		dump_stack_lvl(KERN_ERR);
42362306a36Sopenharmony_ci		return -EINVAL;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci	va_start(args, fmt);
42662306a36Sopenharmony_ci	retval = kobject_add_varg(kobj, parent, fmt, args);
42762306a36Sopenharmony_ci	va_end(args);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	return retval;
43062306a36Sopenharmony_ci}
43162306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_add);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci/**
43462306a36Sopenharmony_ci * kobject_init_and_add() - Initialize a kobject structure and add it to
43562306a36Sopenharmony_ci *                          the kobject hierarchy.
43662306a36Sopenharmony_ci * @kobj: pointer to the kobject to initialize
43762306a36Sopenharmony_ci * @ktype: pointer to the ktype for this kobject.
43862306a36Sopenharmony_ci * @parent: pointer to the parent of this kobject.
43962306a36Sopenharmony_ci * @fmt: the name of the kobject.
44062306a36Sopenharmony_ci *
44162306a36Sopenharmony_ci * This function combines the call to kobject_init() and kobject_add().
44262306a36Sopenharmony_ci *
44362306a36Sopenharmony_ci * If this function returns an error, kobject_put() must be called to
44462306a36Sopenharmony_ci * properly clean up the memory associated with the object.  This is the
44562306a36Sopenharmony_ci * same type of error handling after a call to kobject_add() and kobject
44662306a36Sopenharmony_ci * lifetime rules are the same here.
44762306a36Sopenharmony_ci */
44862306a36Sopenharmony_ciint kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype,
44962306a36Sopenharmony_ci			 struct kobject *parent, const char *fmt, ...)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	va_list args;
45262306a36Sopenharmony_ci	int retval;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	kobject_init(kobj, ktype);
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	va_start(args, fmt);
45762306a36Sopenharmony_ci	retval = kobject_add_varg(kobj, parent, fmt, args);
45862306a36Sopenharmony_ci	va_end(args);
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	return retval;
46162306a36Sopenharmony_ci}
46262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobject_init_and_add);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci/**
46562306a36Sopenharmony_ci * kobject_rename() - Change the name of an object.
46662306a36Sopenharmony_ci * @kobj: object in question.
46762306a36Sopenharmony_ci * @new_name: object's new name
46862306a36Sopenharmony_ci *
46962306a36Sopenharmony_ci * It is the responsibility of the caller to provide mutual
47062306a36Sopenharmony_ci * exclusion between two different calls of kobject_rename
47162306a36Sopenharmony_ci * on the same kobject and to ensure that new_name is valid and
47262306a36Sopenharmony_ci * won't conflict with other kobjects.
47362306a36Sopenharmony_ci */
47462306a36Sopenharmony_ciint kobject_rename(struct kobject *kobj, const char *new_name)
47562306a36Sopenharmony_ci{
47662306a36Sopenharmony_ci	int error = 0;
47762306a36Sopenharmony_ci	const char *devpath = NULL;
47862306a36Sopenharmony_ci	const char *dup_name = NULL, *name;
47962306a36Sopenharmony_ci	char *devpath_string = NULL;
48062306a36Sopenharmony_ci	char *envp[2];
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	kobj = kobject_get(kobj);
48362306a36Sopenharmony_ci	if (!kobj)
48462306a36Sopenharmony_ci		return -EINVAL;
48562306a36Sopenharmony_ci	if (!kobj->parent) {
48662306a36Sopenharmony_ci		kobject_put(kobj);
48762306a36Sopenharmony_ci		return -EINVAL;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	devpath = kobject_get_path(kobj, GFP_KERNEL);
49162306a36Sopenharmony_ci	if (!devpath) {
49262306a36Sopenharmony_ci		error = -ENOMEM;
49362306a36Sopenharmony_ci		goto out;
49462306a36Sopenharmony_ci	}
49562306a36Sopenharmony_ci	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
49662306a36Sopenharmony_ci	if (!devpath_string) {
49762306a36Sopenharmony_ci		error = -ENOMEM;
49862306a36Sopenharmony_ci		goto out;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
50162306a36Sopenharmony_ci	envp[0] = devpath_string;
50262306a36Sopenharmony_ci	envp[1] = NULL;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	name = dup_name = kstrdup_const(new_name, GFP_KERNEL);
50562306a36Sopenharmony_ci	if (!name) {
50662306a36Sopenharmony_ci		error = -ENOMEM;
50762306a36Sopenharmony_ci		goto out;
50862306a36Sopenharmony_ci	}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj));
51162306a36Sopenharmony_ci	if (error)
51262306a36Sopenharmony_ci		goto out;
51362306a36Sopenharmony_ci
51462306a36Sopenharmony_ci	/* Install the new kobject name */
51562306a36Sopenharmony_ci	dup_name = kobj->name;
51662306a36Sopenharmony_ci	kobj->name = name;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/* This function is mostly/only used for network interface.
51962306a36Sopenharmony_ci	 * Some hotplug package track interfaces by their name and
52062306a36Sopenharmony_ci	 * therefore want to know when the name is changed by the user. */
52162306a36Sopenharmony_ci	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ciout:
52462306a36Sopenharmony_ci	kfree_const(dup_name);
52562306a36Sopenharmony_ci	kfree(devpath_string);
52662306a36Sopenharmony_ci	kfree(devpath);
52762306a36Sopenharmony_ci	kobject_put(kobj);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	return error;
53062306a36Sopenharmony_ci}
53162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobject_rename);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci/**
53462306a36Sopenharmony_ci * kobject_move() - Move object to another parent.
53562306a36Sopenharmony_ci * @kobj: object in question.
53662306a36Sopenharmony_ci * @new_parent: object's new parent (can be NULL)
53762306a36Sopenharmony_ci */
53862306a36Sopenharmony_ciint kobject_move(struct kobject *kobj, struct kobject *new_parent)
53962306a36Sopenharmony_ci{
54062306a36Sopenharmony_ci	int error;
54162306a36Sopenharmony_ci	struct kobject *old_parent;
54262306a36Sopenharmony_ci	const char *devpath = NULL;
54362306a36Sopenharmony_ci	char *devpath_string = NULL;
54462306a36Sopenharmony_ci	char *envp[2];
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	kobj = kobject_get(kobj);
54762306a36Sopenharmony_ci	if (!kobj)
54862306a36Sopenharmony_ci		return -EINVAL;
54962306a36Sopenharmony_ci	new_parent = kobject_get(new_parent);
55062306a36Sopenharmony_ci	if (!new_parent) {
55162306a36Sopenharmony_ci		if (kobj->kset)
55262306a36Sopenharmony_ci			new_parent = kobject_get(&kobj->kset->kobj);
55362306a36Sopenharmony_ci	}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	/* old object path */
55662306a36Sopenharmony_ci	devpath = kobject_get_path(kobj, GFP_KERNEL);
55762306a36Sopenharmony_ci	if (!devpath) {
55862306a36Sopenharmony_ci		error = -ENOMEM;
55962306a36Sopenharmony_ci		goto out;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
56262306a36Sopenharmony_ci	if (!devpath_string) {
56362306a36Sopenharmony_ci		error = -ENOMEM;
56462306a36Sopenharmony_ci		goto out;
56562306a36Sopenharmony_ci	}
56662306a36Sopenharmony_ci	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
56762306a36Sopenharmony_ci	envp[0] = devpath_string;
56862306a36Sopenharmony_ci	envp[1] = NULL;
56962306a36Sopenharmony_ci	error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj));
57062306a36Sopenharmony_ci	if (error)
57162306a36Sopenharmony_ci		goto out;
57262306a36Sopenharmony_ci	old_parent = kobj->parent;
57362306a36Sopenharmony_ci	kobj->parent = new_parent;
57462306a36Sopenharmony_ci	new_parent = NULL;
57562306a36Sopenharmony_ci	kobject_put(old_parent);
57662306a36Sopenharmony_ci	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
57762306a36Sopenharmony_ciout:
57862306a36Sopenharmony_ci	kobject_put(new_parent);
57962306a36Sopenharmony_ci	kobject_put(kobj);
58062306a36Sopenharmony_ci	kfree(devpath_string);
58162306a36Sopenharmony_ci	kfree(devpath);
58262306a36Sopenharmony_ci	return error;
58362306a36Sopenharmony_ci}
58462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobject_move);
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_cistatic void __kobject_del(struct kobject *kobj)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	struct kernfs_node *sd;
58962306a36Sopenharmony_ci	const struct kobj_type *ktype;
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	sd = kobj->sd;
59262306a36Sopenharmony_ci	ktype = get_ktype(kobj);
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	if (ktype)
59562306a36Sopenharmony_ci		sysfs_remove_groups(kobj, ktype->default_groups);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	/* send "remove" if the caller did not do it but sent "add" */
59862306a36Sopenharmony_ci	if (kobj->state_add_uevent_sent && !kobj->state_remove_uevent_sent) {
59962306a36Sopenharmony_ci		pr_debug("'%s' (%p): auto cleanup 'remove' event\n",
60062306a36Sopenharmony_ci			 kobject_name(kobj), kobj);
60162306a36Sopenharmony_ci		kobject_uevent(kobj, KOBJ_REMOVE);
60262306a36Sopenharmony_ci	}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	sysfs_remove_dir(kobj);
60562306a36Sopenharmony_ci	sysfs_put(sd);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	kobj->state_in_sysfs = 0;
60862306a36Sopenharmony_ci	kobj_kset_leave(kobj);
60962306a36Sopenharmony_ci	kobj->parent = NULL;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_ci/**
61362306a36Sopenharmony_ci * kobject_del() - Unlink kobject from hierarchy.
61462306a36Sopenharmony_ci * @kobj: object.
61562306a36Sopenharmony_ci *
61662306a36Sopenharmony_ci * This is the function that should be called to delete an object
61762306a36Sopenharmony_ci * successfully added via kobject_add().
61862306a36Sopenharmony_ci */
61962306a36Sopenharmony_civoid kobject_del(struct kobject *kobj)
62062306a36Sopenharmony_ci{
62162306a36Sopenharmony_ci	struct kobject *parent;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	if (!kobj)
62462306a36Sopenharmony_ci		return;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	parent = kobj->parent;
62762306a36Sopenharmony_ci	__kobject_del(kobj);
62862306a36Sopenharmony_ci	kobject_put(parent);
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_del);
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci/**
63362306a36Sopenharmony_ci * kobject_get() - Increment refcount for object.
63462306a36Sopenharmony_ci * @kobj: object.
63562306a36Sopenharmony_ci */
63662306a36Sopenharmony_cistruct kobject *kobject_get(struct kobject *kobj)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	if (kobj) {
63962306a36Sopenharmony_ci		if (!kobj->state_initialized)
64062306a36Sopenharmony_ci			WARN(1, KERN_WARNING
64162306a36Sopenharmony_ci				"kobject: '%s' (%p): is not initialized, yet kobject_get() is being called.\n",
64262306a36Sopenharmony_ci			     kobject_name(kobj), kobj);
64362306a36Sopenharmony_ci		kref_get(&kobj->kref);
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci	return kobj;
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_get);
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_cistruct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	if (!kobj)
65262306a36Sopenharmony_ci		return NULL;
65362306a36Sopenharmony_ci	if (!kref_get_unless_zero(&kobj->kref))
65462306a36Sopenharmony_ci		kobj = NULL;
65562306a36Sopenharmony_ci	return kobj;
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_get_unless_zero);
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_ci/*
66062306a36Sopenharmony_ci * kobject_cleanup - free kobject resources.
66162306a36Sopenharmony_ci * @kobj: object to cleanup
66262306a36Sopenharmony_ci */
66362306a36Sopenharmony_cistatic void kobject_cleanup(struct kobject *kobj)
66462306a36Sopenharmony_ci{
66562306a36Sopenharmony_ci	struct kobject *parent = kobj->parent;
66662306a36Sopenharmony_ci	const struct kobj_type *t = get_ktype(kobj);
66762306a36Sopenharmony_ci	const char *name = kobj->name;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	pr_debug("'%s' (%p): %s, parent %p\n",
67062306a36Sopenharmony_ci		 kobject_name(kobj), kobj, __func__, kobj->parent);
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	if (t && !t->release)
67362306a36Sopenharmony_ci		pr_debug("'%s' (%p): does not have a release() function, it is broken and must be fixed. See Documentation/core-api/kobject.rst.\n",
67462306a36Sopenharmony_ci			 kobject_name(kobj), kobj);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	/* remove from sysfs if the caller did not do it */
67762306a36Sopenharmony_ci	if (kobj->state_in_sysfs) {
67862306a36Sopenharmony_ci		pr_debug("'%s' (%p): auto cleanup kobject_del\n",
67962306a36Sopenharmony_ci			 kobject_name(kobj), kobj);
68062306a36Sopenharmony_ci		__kobject_del(kobj);
68162306a36Sopenharmony_ci	} else {
68262306a36Sopenharmony_ci		/* avoid dropping the parent reference unnecessarily */
68362306a36Sopenharmony_ci		parent = NULL;
68462306a36Sopenharmony_ci	}
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	if (t && t->release) {
68762306a36Sopenharmony_ci		pr_debug("'%s' (%p): calling ktype release\n",
68862306a36Sopenharmony_ci			 kobject_name(kobj), kobj);
68962306a36Sopenharmony_ci		t->release(kobj);
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	/* free name if we allocated it */
69362306a36Sopenharmony_ci	if (name) {
69462306a36Sopenharmony_ci		pr_debug("'%s': free name\n", name);
69562306a36Sopenharmony_ci		kfree_const(name);
69662306a36Sopenharmony_ci	}
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	kobject_put(parent);
69962306a36Sopenharmony_ci}
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
70262306a36Sopenharmony_cistatic void kobject_delayed_cleanup(struct work_struct *work)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	kobject_cleanup(container_of(to_delayed_work(work),
70562306a36Sopenharmony_ci				     struct kobject, release));
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci#endif
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cistatic void kobject_release(struct kref *kref)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	struct kobject *kobj = container_of(kref, struct kobject, kref);
71262306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
71362306a36Sopenharmony_ci	unsigned long delay = HZ + HZ * get_random_u32_below(4);
71462306a36Sopenharmony_ci	pr_info("'%s' (%p): %s, parent %p (delayed %ld)\n",
71562306a36Sopenharmony_ci		kobject_name(kobj), kobj, __func__, kobj->parent, delay);
71662306a36Sopenharmony_ci	INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	schedule_delayed_work(&kobj->release, delay);
71962306a36Sopenharmony_ci#else
72062306a36Sopenharmony_ci	kobject_cleanup(kobj);
72162306a36Sopenharmony_ci#endif
72262306a36Sopenharmony_ci}
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci/**
72562306a36Sopenharmony_ci * kobject_put() - Decrement refcount for object.
72662306a36Sopenharmony_ci * @kobj: object.
72762306a36Sopenharmony_ci *
72862306a36Sopenharmony_ci * Decrement the refcount, and if 0, call kobject_cleanup().
72962306a36Sopenharmony_ci */
73062306a36Sopenharmony_civoid kobject_put(struct kobject *kobj)
73162306a36Sopenharmony_ci{
73262306a36Sopenharmony_ci	if (kobj) {
73362306a36Sopenharmony_ci		if (!kobj->state_initialized)
73462306a36Sopenharmony_ci			WARN(1, KERN_WARNING
73562306a36Sopenharmony_ci				"kobject: '%s' (%p): is not initialized, yet kobject_put() is being called.\n",
73662306a36Sopenharmony_ci			     kobject_name(kobj), kobj);
73762306a36Sopenharmony_ci		kref_put(&kobj->kref, kobject_release);
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci}
74062306a36Sopenharmony_ciEXPORT_SYMBOL(kobject_put);
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_cistatic void dynamic_kobj_release(struct kobject *kobj)
74362306a36Sopenharmony_ci{
74462306a36Sopenharmony_ci	pr_debug("(%p): %s\n", kobj, __func__);
74562306a36Sopenharmony_ci	kfree(kobj);
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic const struct kobj_type dynamic_kobj_ktype = {
74962306a36Sopenharmony_ci	.release	= dynamic_kobj_release,
75062306a36Sopenharmony_ci	.sysfs_ops	= &kobj_sysfs_ops,
75162306a36Sopenharmony_ci};
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci/**
75462306a36Sopenharmony_ci * kobject_create() - Create a struct kobject dynamically.
75562306a36Sopenharmony_ci *
75662306a36Sopenharmony_ci * This function creates a kobject structure dynamically and sets it up
75762306a36Sopenharmony_ci * to be a "dynamic" kobject with a default release function set up.
75862306a36Sopenharmony_ci *
75962306a36Sopenharmony_ci * If the kobject was not able to be created, NULL will be returned.
76062306a36Sopenharmony_ci * The kobject structure returned from here must be cleaned up with a
76162306a36Sopenharmony_ci * call to kobject_put() and not kfree(), as kobject_init() has
76262306a36Sopenharmony_ci * already been called on this structure.
76362306a36Sopenharmony_ci */
76462306a36Sopenharmony_cistatic struct kobject *kobject_create(void)
76562306a36Sopenharmony_ci{
76662306a36Sopenharmony_ci	struct kobject *kobj;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
76962306a36Sopenharmony_ci	if (!kobj)
77062306a36Sopenharmony_ci		return NULL;
77162306a36Sopenharmony_ci
77262306a36Sopenharmony_ci	kobject_init(kobj, &dynamic_kobj_ktype);
77362306a36Sopenharmony_ci	return kobj;
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci/**
77762306a36Sopenharmony_ci * kobject_create_and_add() - Create a struct kobject dynamically and
77862306a36Sopenharmony_ci *                            register it with sysfs.
77962306a36Sopenharmony_ci * @name: the name for the kobject
78062306a36Sopenharmony_ci * @parent: the parent kobject of this kobject, if any.
78162306a36Sopenharmony_ci *
78262306a36Sopenharmony_ci * This function creates a kobject structure dynamically and registers it
78362306a36Sopenharmony_ci * with sysfs.  When you are finished with this structure, call
78462306a36Sopenharmony_ci * kobject_put() and the structure will be dynamically freed when
78562306a36Sopenharmony_ci * it is no longer being used.
78662306a36Sopenharmony_ci *
78762306a36Sopenharmony_ci * If the kobject was not able to be created, NULL will be returned.
78862306a36Sopenharmony_ci */
78962306a36Sopenharmony_cistruct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
79062306a36Sopenharmony_ci{
79162306a36Sopenharmony_ci	struct kobject *kobj;
79262306a36Sopenharmony_ci	int retval;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	kobj = kobject_create();
79562306a36Sopenharmony_ci	if (!kobj)
79662306a36Sopenharmony_ci		return NULL;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	retval = kobject_add(kobj, parent, "%s", name);
79962306a36Sopenharmony_ci	if (retval) {
80062306a36Sopenharmony_ci		pr_warn("%s: kobject_add error: %d\n", __func__, retval);
80162306a36Sopenharmony_ci		kobject_put(kobj);
80262306a36Sopenharmony_ci		kobj = NULL;
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci	return kobj;
80562306a36Sopenharmony_ci}
80662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobject_create_and_add);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci/**
80962306a36Sopenharmony_ci * kset_init() - Initialize a kset for use.
81062306a36Sopenharmony_ci * @k: kset
81162306a36Sopenharmony_ci */
81262306a36Sopenharmony_civoid kset_init(struct kset *k)
81362306a36Sopenharmony_ci{
81462306a36Sopenharmony_ci	kobject_init_internal(&k->kobj);
81562306a36Sopenharmony_ci	INIT_LIST_HEAD(&k->list);
81662306a36Sopenharmony_ci	spin_lock_init(&k->list_lock);
81762306a36Sopenharmony_ci}
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci/* default kobject attribute operations */
82062306a36Sopenharmony_cistatic ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
82162306a36Sopenharmony_ci			      char *buf)
82262306a36Sopenharmony_ci{
82362306a36Sopenharmony_ci	struct kobj_attribute *kattr;
82462306a36Sopenharmony_ci	ssize_t ret = -EIO;
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	kattr = container_of(attr, struct kobj_attribute, attr);
82762306a36Sopenharmony_ci	if (kattr->show)
82862306a36Sopenharmony_ci		ret = kattr->show(kobj, kattr, buf);
82962306a36Sopenharmony_ci	return ret;
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
83362306a36Sopenharmony_ci			       const char *buf, size_t count)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	struct kobj_attribute *kattr;
83662306a36Sopenharmony_ci	ssize_t ret = -EIO;
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	kattr = container_of(attr, struct kobj_attribute, attr);
83962306a36Sopenharmony_ci	if (kattr->store)
84062306a36Sopenharmony_ci		ret = kattr->store(kobj, kattr, buf, count);
84162306a36Sopenharmony_ci	return ret;
84262306a36Sopenharmony_ci}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ciconst struct sysfs_ops kobj_sysfs_ops = {
84562306a36Sopenharmony_ci	.show	= kobj_attr_show,
84662306a36Sopenharmony_ci	.store	= kobj_attr_store,
84762306a36Sopenharmony_ci};
84862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobj_sysfs_ops);
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_ci/**
85162306a36Sopenharmony_ci * kset_register() - Initialize and add a kset.
85262306a36Sopenharmony_ci * @k: kset.
85362306a36Sopenharmony_ci *
85462306a36Sopenharmony_ci * NOTE: On error, the kset.kobj.name allocated by() kobj_set_name()
85562306a36Sopenharmony_ci * is freed, it can not be used any more.
85662306a36Sopenharmony_ci */
85762306a36Sopenharmony_ciint kset_register(struct kset *k)
85862306a36Sopenharmony_ci{
85962306a36Sopenharmony_ci	int err;
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	if (!k)
86262306a36Sopenharmony_ci		return -EINVAL;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	if (!k->kobj.ktype) {
86562306a36Sopenharmony_ci		pr_err("must have a ktype to be initialized properly!\n");
86662306a36Sopenharmony_ci		return -EINVAL;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	kset_init(k);
87062306a36Sopenharmony_ci	err = kobject_add_internal(&k->kobj);
87162306a36Sopenharmony_ci	if (err) {
87262306a36Sopenharmony_ci		kfree_const(k->kobj.name);
87362306a36Sopenharmony_ci		/* Set it to NULL to avoid accessing bad pointer in callers. */
87462306a36Sopenharmony_ci		k->kobj.name = NULL;
87562306a36Sopenharmony_ci		return err;
87662306a36Sopenharmony_ci	}
87762306a36Sopenharmony_ci	kobject_uevent(&k->kobj, KOBJ_ADD);
87862306a36Sopenharmony_ci	return 0;
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ciEXPORT_SYMBOL(kset_register);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci/**
88362306a36Sopenharmony_ci * kset_unregister() - Remove a kset.
88462306a36Sopenharmony_ci * @k: kset.
88562306a36Sopenharmony_ci */
88662306a36Sopenharmony_civoid kset_unregister(struct kset *k)
88762306a36Sopenharmony_ci{
88862306a36Sopenharmony_ci	if (!k)
88962306a36Sopenharmony_ci		return;
89062306a36Sopenharmony_ci	kobject_del(&k->kobj);
89162306a36Sopenharmony_ci	kobject_put(&k->kobj);
89262306a36Sopenharmony_ci}
89362306a36Sopenharmony_ciEXPORT_SYMBOL(kset_unregister);
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci/**
89662306a36Sopenharmony_ci * kset_find_obj() - Search for object in kset.
89762306a36Sopenharmony_ci * @kset: kset we're looking in.
89862306a36Sopenharmony_ci * @name: object's name.
89962306a36Sopenharmony_ci *
90062306a36Sopenharmony_ci * Lock kset via @kset->subsys, and iterate over @kset->list,
90162306a36Sopenharmony_ci * looking for a matching kobject. If matching object is found
90262306a36Sopenharmony_ci * take a reference and return the object.
90362306a36Sopenharmony_ci */
90462306a36Sopenharmony_cistruct kobject *kset_find_obj(struct kset *kset, const char *name)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	struct kobject *k;
90762306a36Sopenharmony_ci	struct kobject *ret = NULL;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	spin_lock(&kset->list_lock);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	list_for_each_entry(k, &kset->list, entry) {
91262306a36Sopenharmony_ci		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
91362306a36Sopenharmony_ci			ret = kobject_get_unless_zero(k);
91462306a36Sopenharmony_ci			break;
91562306a36Sopenharmony_ci		}
91662306a36Sopenharmony_ci	}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	spin_unlock(&kset->list_lock);
91962306a36Sopenharmony_ci	return ret;
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kset_find_obj);
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cistatic void kset_release(struct kobject *kobj)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	struct kset *kset = container_of(kobj, struct kset, kobj);
92662306a36Sopenharmony_ci	pr_debug("'%s' (%p): %s\n",
92762306a36Sopenharmony_ci		 kobject_name(kobj), kobj, __func__);
92862306a36Sopenharmony_ci	kfree(kset);
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cistatic void kset_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	if (kobj->parent)
93462306a36Sopenharmony_ci		kobject_get_ownership(kobj->parent, uid, gid);
93562306a36Sopenharmony_ci}
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_cistatic const struct kobj_type kset_ktype = {
93862306a36Sopenharmony_ci	.sysfs_ops	= &kobj_sysfs_ops,
93962306a36Sopenharmony_ci	.release	= kset_release,
94062306a36Sopenharmony_ci	.get_ownership	= kset_get_ownership,
94162306a36Sopenharmony_ci};
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci/**
94462306a36Sopenharmony_ci * kset_create() - Create a struct kset dynamically.
94562306a36Sopenharmony_ci *
94662306a36Sopenharmony_ci * @name: the name for the kset
94762306a36Sopenharmony_ci * @uevent_ops: a struct kset_uevent_ops for the kset
94862306a36Sopenharmony_ci * @parent_kobj: the parent kobject of this kset, if any.
94962306a36Sopenharmony_ci *
95062306a36Sopenharmony_ci * This function creates a kset structure dynamically.  This structure can
95162306a36Sopenharmony_ci * then be registered with the system and show up in sysfs with a call to
95262306a36Sopenharmony_ci * kset_register().  When you are finished with this structure, if
95362306a36Sopenharmony_ci * kset_register() has been called, call kset_unregister() and the
95462306a36Sopenharmony_ci * structure will be dynamically freed when it is no longer being used.
95562306a36Sopenharmony_ci *
95662306a36Sopenharmony_ci * If the kset was not able to be created, NULL will be returned.
95762306a36Sopenharmony_ci */
95862306a36Sopenharmony_cistatic struct kset *kset_create(const char *name,
95962306a36Sopenharmony_ci				const struct kset_uevent_ops *uevent_ops,
96062306a36Sopenharmony_ci				struct kobject *parent_kobj)
96162306a36Sopenharmony_ci{
96262306a36Sopenharmony_ci	struct kset *kset;
96362306a36Sopenharmony_ci	int retval;
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	kset = kzalloc(sizeof(*kset), GFP_KERNEL);
96662306a36Sopenharmony_ci	if (!kset)
96762306a36Sopenharmony_ci		return NULL;
96862306a36Sopenharmony_ci	retval = kobject_set_name(&kset->kobj, "%s", name);
96962306a36Sopenharmony_ci	if (retval) {
97062306a36Sopenharmony_ci		kfree(kset);
97162306a36Sopenharmony_ci		return NULL;
97262306a36Sopenharmony_ci	}
97362306a36Sopenharmony_ci	kset->uevent_ops = uevent_ops;
97462306a36Sopenharmony_ci	kset->kobj.parent = parent_kobj;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	/*
97762306a36Sopenharmony_ci	 * The kobject of this kset will have a type of kset_ktype and belong to
97862306a36Sopenharmony_ci	 * no kset itself.  That way we can properly free it when it is
97962306a36Sopenharmony_ci	 * finished being used.
98062306a36Sopenharmony_ci	 */
98162306a36Sopenharmony_ci	kset->kobj.ktype = &kset_ktype;
98262306a36Sopenharmony_ci	kset->kobj.kset = NULL;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	return kset;
98562306a36Sopenharmony_ci}
98662306a36Sopenharmony_ci
98762306a36Sopenharmony_ci/**
98862306a36Sopenharmony_ci * kset_create_and_add() - Create a struct kset dynamically and add it to sysfs.
98962306a36Sopenharmony_ci *
99062306a36Sopenharmony_ci * @name: the name for the kset
99162306a36Sopenharmony_ci * @uevent_ops: a struct kset_uevent_ops for the kset
99262306a36Sopenharmony_ci * @parent_kobj: the parent kobject of this kset, if any.
99362306a36Sopenharmony_ci *
99462306a36Sopenharmony_ci * This function creates a kset structure dynamically and registers it
99562306a36Sopenharmony_ci * with sysfs.  When you are finished with this structure, call
99662306a36Sopenharmony_ci * kset_unregister() and the structure will be dynamically freed when it
99762306a36Sopenharmony_ci * is no longer being used.
99862306a36Sopenharmony_ci *
99962306a36Sopenharmony_ci * If the kset was not able to be created, NULL will be returned.
100062306a36Sopenharmony_ci */
100162306a36Sopenharmony_cistruct kset *kset_create_and_add(const char *name,
100262306a36Sopenharmony_ci				 const struct kset_uevent_ops *uevent_ops,
100362306a36Sopenharmony_ci				 struct kobject *parent_kobj)
100462306a36Sopenharmony_ci{
100562306a36Sopenharmony_ci	struct kset *kset;
100662306a36Sopenharmony_ci	int error;
100762306a36Sopenharmony_ci
100862306a36Sopenharmony_ci	kset = kset_create(name, uevent_ops, parent_kobj);
100962306a36Sopenharmony_ci	if (!kset)
101062306a36Sopenharmony_ci		return NULL;
101162306a36Sopenharmony_ci	error = kset_register(kset);
101262306a36Sopenharmony_ci	if (error) {
101362306a36Sopenharmony_ci		kfree(kset);
101462306a36Sopenharmony_ci		return NULL;
101562306a36Sopenharmony_ci	}
101662306a36Sopenharmony_ci	return kset;
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kset_create_and_add);
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_cistatic DEFINE_SPINLOCK(kobj_ns_type_lock);
102262306a36Sopenharmony_cistatic const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ciint kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
102562306a36Sopenharmony_ci{
102662306a36Sopenharmony_ci	enum kobj_ns_type type = ops->type;
102762306a36Sopenharmony_ci	int error;
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci	error = -EINVAL;
103262306a36Sopenharmony_ci	if (!kobj_ns_type_is_valid(type))
103362306a36Sopenharmony_ci		goto out;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	error = -EBUSY;
103662306a36Sopenharmony_ci	if (kobj_ns_ops_tbl[type])
103762306a36Sopenharmony_ci		goto out;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	error = 0;
104062306a36Sopenharmony_ci	kobj_ns_ops_tbl[type] = ops;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ciout:
104362306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
104462306a36Sopenharmony_ci	return error;
104562306a36Sopenharmony_ci}
104662306a36Sopenharmony_ci
104762306a36Sopenharmony_ciint kobj_ns_type_registered(enum kobj_ns_type type)
104862306a36Sopenharmony_ci{
104962306a36Sopenharmony_ci	int registered = 0;
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
105262306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type))
105362306a36Sopenharmony_ci		registered = kobj_ns_ops_tbl[type] != NULL;
105462306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	return registered;
105762306a36Sopenharmony_ci}
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ciconst struct kobj_ns_type_operations *kobj_child_ns_ops(const struct kobject *parent)
106062306a36Sopenharmony_ci{
106162306a36Sopenharmony_ci	const struct kobj_ns_type_operations *ops = NULL;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	if (parent && parent->ktype && parent->ktype->child_ns_type)
106462306a36Sopenharmony_ci		ops = parent->ktype->child_ns_type(parent);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	return ops;
106762306a36Sopenharmony_ci}
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ciconst struct kobj_ns_type_operations *kobj_ns_ops(const struct kobject *kobj)
107062306a36Sopenharmony_ci{
107162306a36Sopenharmony_ci	return kobj_child_ns_ops(kobj->parent);
107262306a36Sopenharmony_ci}
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_cibool kobj_ns_current_may_mount(enum kobj_ns_type type)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	bool may_mount = true;
107762306a36Sopenharmony_ci
107862306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
107962306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
108062306a36Sopenharmony_ci		may_mount = kobj_ns_ops_tbl[type]->current_may_mount();
108162306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
108262306a36Sopenharmony_ci
108362306a36Sopenharmony_ci	return may_mount;
108462306a36Sopenharmony_ci}
108562306a36Sopenharmony_ci
108662306a36Sopenharmony_civoid *kobj_ns_grab_current(enum kobj_ns_type type)
108762306a36Sopenharmony_ci{
108862306a36Sopenharmony_ci	void *ns = NULL;
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
109162306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
109262306a36Sopenharmony_ci		ns = kobj_ns_ops_tbl[type]->grab_current_ns();
109362306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return ns;
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobj_ns_grab_current);
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ciconst void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk)
110062306a36Sopenharmony_ci{
110162306a36Sopenharmony_ci	const void *ns = NULL;
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
110462306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
110562306a36Sopenharmony_ci		ns = kobj_ns_ops_tbl[type]->netlink_ns(sk);
110662306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	return ns;
110962306a36Sopenharmony_ci}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ciconst void *kobj_ns_initial(enum kobj_ns_type type)
111262306a36Sopenharmony_ci{
111362306a36Sopenharmony_ci	const void *ns = NULL;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
111662306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
111762306a36Sopenharmony_ci		ns = kobj_ns_ops_tbl[type]->initial_ns();
111862306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_ci	return ns;
112162306a36Sopenharmony_ci}
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_civoid kobj_ns_drop(enum kobj_ns_type type, void *ns)
112462306a36Sopenharmony_ci{
112562306a36Sopenharmony_ci	spin_lock(&kobj_ns_type_lock);
112662306a36Sopenharmony_ci	if (kobj_ns_type_is_valid(type) &&
112762306a36Sopenharmony_ci	    kobj_ns_ops_tbl[type] && kobj_ns_ops_tbl[type]->drop_ns)
112862306a36Sopenharmony_ci		kobj_ns_ops_tbl[type]->drop_ns(ns);
112962306a36Sopenharmony_ci	spin_unlock(&kobj_ns_type_lock);
113062306a36Sopenharmony_ci}
113162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(kobj_ns_drop);
1132