xref: /openbmc/linux/lib/kobject.c (revision 7f414d30)
1d9d16e16SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * kobject.c - library routines for handling generic kernel objects
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
6f0e7e1bdSGreg Kroah-Hartman  * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com>
7f0e7e1bdSGreg Kroah-Hartman  * Copyright (c) 2006-2007 Novell Inc.
81da177e4SLinus Torvalds  *
90c1bc6b8SMauro Carvalho Chehab  * Please see the file Documentation/core-api/kobject.rst for critical information
101da177e4SLinus Torvalds  * about using the kobject interface.
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
1398406333SThomas Weißschuh #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1498406333SThomas Weißschuh 
151da177e4SLinus Torvalds #include <linux/kobject.h>
161da177e4SLinus Torvalds #include <linux/string.h>
178bc3bcc9SPaul Gortmaker #include <linux/export.h>
181da177e4SLinus Torvalds #include <linux/stat.h>
194e57b681STim Schmielau #include <linux/slab.h>
2089c86a64SBjorn Helgaas #include <linux/random.h>
211da177e4SLinus Torvalds 
22e34ff490STejun Heo /**
23ed856349STobin C. Harding  * kobject_namespace() - Return @kobj's namespace tag.
24e34ff490STejun Heo  * @kobj: kobject in question
25e34ff490STejun Heo  *
26e34ff490STejun Heo  * Returns namespace tag of @kobj if its parent has namespace ops enabled
27e34ff490STejun Heo  * and thus @kobj should have a namespace tag associated with it.  Returns
28e34ff490STejun Heo  * %NULL otherwise.
29e34ff490STejun Heo  */
kobject_namespace(const struct kobject * kobj)30542aa246SGreg Kroah-Hartman const void *kobject_namespace(const struct kobject *kobj)
31e34ff490STejun Heo {
32e34ff490STejun Heo 	const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj);
33e34ff490STejun Heo 
34e34ff490STejun Heo 	if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE)
35e34ff490STejun Heo 		return NULL;
36e34ff490STejun Heo 
37a1212d27SLinus Torvalds 	return kobj->ktype->namespace(kobj);
38e34ff490STejun Heo }
39e34ff490STejun Heo 
405f81880dSDmitry Torokhov /**
41ed856349STobin C. Harding  * kobject_get_ownership() - Get sysfs ownership data for @kobj.
425f81880dSDmitry Torokhov  * @kobj: kobject in question
435f81880dSDmitry Torokhov  * @uid: kernel user ID for sysfs objects
445f81880dSDmitry Torokhov  * @gid: kernel group ID for sysfs objects
455f81880dSDmitry Torokhov  *
465f81880dSDmitry Torokhov  * Returns initial uid/gid pair that should be used when creating sysfs
475f81880dSDmitry Torokhov  * representation of given kobject. Normally used to adjust ownership of
485f81880dSDmitry Torokhov  * objects in a container.
495f81880dSDmitry Torokhov  */
kobject_get_ownership(const struct kobject * kobj,kuid_t * uid,kgid_t * gid)5002a476d9SGreg Kroah-Hartman void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
515f81880dSDmitry Torokhov {
525f81880dSDmitry Torokhov 	*uid = GLOBAL_ROOT_UID;
535f81880dSDmitry Torokhov 	*gid = GLOBAL_ROOT_GID;
545f81880dSDmitry Torokhov 
555f81880dSDmitry Torokhov 	if (kobj->ktype->get_ownership)
565f81880dSDmitry Torokhov 		kobj->ktype->get_ownership(kobj, uid, gid);
575f81880dSDmitry Torokhov }
585f81880dSDmitry Torokhov 
kobj_ns_type_is_valid(enum kobj_ns_type type)59e2dfa1d5SZhen Lei static bool kobj_ns_type_is_valid(enum kobj_ns_type type)
60e2dfa1d5SZhen Lei {
61e2dfa1d5SZhen Lei 	if ((type <= KOBJ_NS_TYPE_NONE) || (type >= KOBJ_NS_TYPES))
62e2dfa1d5SZhen Lei 		return false;
63e2dfa1d5SZhen Lei 
64e2dfa1d5SZhen Lei 	return true;
65e2dfa1d5SZhen Lei }
66e2dfa1d5SZhen Lei 
create_dir(struct kobject * kobj)6790bc6135SEric W. Biederman static int create_dir(struct kobject *kobj)
681da177e4SLinus Torvalds {
69aa30f47cSKimberly Brown 	const struct kobj_type *ktype = get_ktype(kobj);
70c84a3b27STejun Heo 	const struct kobj_ns_type_operations *ops;
71e34ff490STejun Heo 	int error;
72e34ff490STejun Heo 
73e34ff490STejun Heo 	error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
74e374a2bfSGreg Kroah-Hartman 	if (error)
75c84a3b27STejun Heo 		return error;
76c84a3b27STejun Heo 
77*7f414d30SGreg Kroah-Hartman 	if (ktype) {
78aa30f47cSKimberly Brown 		error = sysfs_create_groups(kobj, ktype->default_groups);
79aa30f47cSKimberly Brown 		if (error) {
80aa30f47cSKimberly Brown 			sysfs_remove_dir(kobj);
81aa30f47cSKimberly Brown 			return error;
82aa30f47cSKimberly Brown 		}
83*7f414d30SGreg Kroah-Hartman 	}
84aa30f47cSKimberly Brown 
8526ea12deSTejun Heo 	/*
8626ea12deSTejun Heo 	 * @kobj->sd may be deleted by an ancestor going away.  Hold an
8726ea12deSTejun Heo 	 * extra reference so that it stays until @kobj is gone.
8826ea12deSTejun Heo 	 */
8926ea12deSTejun Heo 	sysfs_get(kobj->sd);
9026ea12deSTejun Heo 
91c84a3b27STejun Heo 	/*
92c84a3b27STejun Heo 	 * If @kobj has ns_ops, its children need to be filtered based on
93c84a3b27STejun Heo 	 * their namespace tags.  Enable namespace support on @kobj->sd.
94c84a3b27STejun Heo 	 */
95c84a3b27STejun Heo 	ops = kobj_child_ns_ops(kobj);
96c84a3b27STejun Heo 	if (ops) {
97e2dfa1d5SZhen Lei 		BUG_ON(!kobj_ns_type_is_valid(ops->type));
98c84a3b27STejun Heo 		BUG_ON(!kobj_ns_type_registered(ops->type));
99c84a3b27STejun Heo 
100fa4cd451STejun Heo 		sysfs_enable_ns(kobj->sd);
101c84a3b27STejun Heo 	}
102c84a3b27STejun Heo 
103c84a3b27STejun Heo 	return 0;
1041da177e4SLinus Torvalds }
1051da177e4SLinus Torvalds 
get_kobj_path_length(const struct kobject * kobj)10633a0a1e3SGreg Kroah-Hartman static int get_kobj_path_length(const struct kobject *kobj)
1071da177e4SLinus Torvalds {
1081da177e4SLinus Torvalds 	int length = 1;
10933a0a1e3SGreg Kroah-Hartman 	const struct kobject *parent = kobj;
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 	/* walk up the ancestors until we hit the one pointing to the
1121da177e4SLinus Torvalds 	 * root.
1131da177e4SLinus Torvalds 	 * Add 1 to strlen for leading '/' of each level.
1141da177e4SLinus Torvalds 	 */
1151da177e4SLinus Torvalds 	do {
116b365b3daSChuck Ebbert 		if (kobject_name(parent) == NULL)
117b365b3daSChuck Ebbert 			return 0;
1181da177e4SLinus Torvalds 		length += strlen(kobject_name(parent)) + 1;
1191da177e4SLinus Torvalds 		parent = parent->parent;
1201da177e4SLinus Torvalds 	} while (parent);
1211da177e4SLinus Torvalds 	return length;
1221da177e4SLinus Torvalds }
1231da177e4SLinus Torvalds 
fill_kobj_path(const struct kobject * kobj,char * path,int length)1243bb2a01cSWang Hai static int fill_kobj_path(const struct kobject *kobj, char *path, int length)
1251da177e4SLinus Torvalds {
12633a0a1e3SGreg Kroah-Hartman 	const struct kobject *parent;
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 	--length;
1291da177e4SLinus Torvalds 	for (parent = kobj; parent; parent = parent->parent) {
1301da177e4SLinus Torvalds 		int cur = strlen(kobject_name(parent));
1311da177e4SLinus Torvalds 		/* back up enough to print this name with '/' */
1321da177e4SLinus Torvalds 		length -= cur;
1333bb2a01cSWang Hai 		if (length <= 0)
1343bb2a01cSWang Hai 			return -EINVAL;
13577d2a24bSGuenter Roeck 		memcpy(path + length, kobject_name(parent), cur);
1361da177e4SLinus Torvalds 		*(path + --length) = '/';
1371da177e4SLinus Torvalds 	}
1381da177e4SLinus Torvalds 
13998406333SThomas Weißschuh 	pr_debug("'%s' (%p): %s: path = '%s'\n", kobject_name(kobj),
140810304dbSHarvey Harrison 		 kobj, __func__, path);
1413bb2a01cSWang Hai 
1423bb2a01cSWang Hai 	return 0;
1431da177e4SLinus Torvalds }
1441da177e4SLinus Torvalds 
1451da177e4SLinus Torvalds /**
1468fd7c302STobin C. Harding  * kobject_get_path() - Allocate memory and fill in the path for @kobj.
1471da177e4SLinus Torvalds  * @kobj:	kobject in question, with which to build the path
1481da177e4SLinus Torvalds  * @gfp_mask:	the allocation type used to allocate the path
14972fd4a35SRobert P. J. Day  *
1508fd7c302STobin C. Harding  * Return: The newly allocated memory, caller must free with kfree().
1511da177e4SLinus Torvalds  */
kobject_get_path(const struct kobject * kobj,gfp_t gfp_mask)15233a0a1e3SGreg Kroah-Hartman char *kobject_get_path(const struct kobject *kobj, gfp_t gfp_mask)
1531da177e4SLinus Torvalds {
1541da177e4SLinus Torvalds 	char *path;
1551da177e4SLinus Torvalds 	int len;
1561da177e4SLinus Torvalds 
1573bb2a01cSWang Hai retry:
1581da177e4SLinus Torvalds 	len = get_kobj_path_length(kobj);
159b365b3daSChuck Ebbert 	if (len == 0)
160b365b3daSChuck Ebbert 		return NULL;
1614668edc3SBurman Yan 	path = kzalloc(len, gfp_mask);
1621da177e4SLinus Torvalds 	if (!path)
1631da177e4SLinus Torvalds 		return NULL;
1643bb2a01cSWang Hai 	if (fill_kobj_path(kobj, path, len)) {
1653bb2a01cSWang Hai 		kfree(path);
1663bb2a01cSWang Hai 		goto retry;
1673bb2a01cSWang Hai 	}
1681da177e4SLinus Torvalds 
1691da177e4SLinus Torvalds 	return path;
1701da177e4SLinus Torvalds }
17180fc9f53SDmitry Torokhov EXPORT_SYMBOL_GPL(kobject_get_path);
1721da177e4SLinus Torvalds 
1730f4dafc0SKay Sievers /* add the kobject to its kset's list */
kobj_kset_join(struct kobject * kobj)1740f4dafc0SKay Sievers static void kobj_kset_join(struct kobject *kobj)
1750f4dafc0SKay Sievers {
1760f4dafc0SKay Sievers 	if (!kobj->kset)
1770f4dafc0SKay Sievers 		return;
1780f4dafc0SKay Sievers 
1790f4dafc0SKay Sievers 	kset_get(kobj->kset);
1800f4dafc0SKay Sievers 	spin_lock(&kobj->kset->list_lock);
1810f4dafc0SKay Sievers 	list_add_tail(&kobj->entry, &kobj->kset->list);
1820f4dafc0SKay Sievers 	spin_unlock(&kobj->kset->list_lock);
1830f4dafc0SKay Sievers }
1840f4dafc0SKay Sievers 
1850f4dafc0SKay Sievers /* remove the kobject from its kset's list */
kobj_kset_leave(struct kobject * kobj)1860f4dafc0SKay Sievers static void kobj_kset_leave(struct kobject *kobj)
1870f4dafc0SKay Sievers {
1880f4dafc0SKay Sievers 	if (!kobj->kset)
1890f4dafc0SKay Sievers 		return;
1900f4dafc0SKay Sievers 
1910f4dafc0SKay Sievers 	spin_lock(&kobj->kset->list_lock);
1920f4dafc0SKay Sievers 	list_del_init(&kobj->entry);
1930f4dafc0SKay Sievers 	spin_unlock(&kobj->kset->list_lock);
1940f4dafc0SKay Sievers 	kset_put(kobj->kset);
1950f4dafc0SKay Sievers }
1960f4dafc0SKay Sievers 
kobject_init_internal(struct kobject * kobj)197e1543ddfSGreg Kroah-Hartman static void kobject_init_internal(struct kobject *kobj)
1981da177e4SLinus Torvalds {
19931b9025aSGreg Kroah-Hartman 	if (!kobj)
20031b9025aSGreg Kroah-Hartman 		return;
2011da177e4SLinus Torvalds 	kref_init(&kobj->kref);
2021da177e4SLinus Torvalds 	INIT_LIST_HEAD(&kobj->entry);
203a4573c48SGreg Kroah-Hartman 	kobj->state_in_sysfs = 0;
204a4573c48SGreg Kroah-Hartman 	kobj->state_add_uevent_sent = 0;
205a4573c48SGreg Kroah-Hartman 	kobj->state_remove_uevent_sent = 0;
206a4573c48SGreg Kroah-Hartman 	kobj->state_initialized = 1;
2071da177e4SLinus Torvalds }
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds 
kobject_add_internal(struct kobject * kobj)2109e7bbccdSGreg Kroah-Hartman static int kobject_add_internal(struct kobject *kobj)
2111da177e4SLinus Torvalds {
2121da177e4SLinus Torvalds 	int error = 0;
2131da177e4SLinus Torvalds 	struct kobject *parent;
2141da177e4SLinus Torvalds 
2150f4dafc0SKay Sievers 	if (!kobj)
2161da177e4SLinus Torvalds 		return -ENOENT;
2170f4dafc0SKay Sievers 
218af5ca3f4SKay Sievers 	if (!kobj->name || !kobj->name[0]) {
21982d1f117SAndy Shevchenko 		WARN(1,
22082d1f117SAndy Shevchenko 		     "kobject: (%p): attempted to be registered with empty name!\n",
22182d1f117SAndy Shevchenko 		     kobj);
222c171fef5SGreg Kroah-Hartman 		return -EINVAL;
223c171fef5SGreg Kroah-Hartman 	}
2240f4dafc0SKay Sievers 
2251da177e4SLinus Torvalds 	parent = kobject_get(kobj->parent);
2261da177e4SLinus Torvalds 
2270f4dafc0SKay Sievers 	/* join kset if set, use it as parent if we do not already have one */
2280f4dafc0SKay Sievers 	if (kobj->kset) {
2290f4dafc0SKay Sievers 		if (!parent)
2300f4dafc0SKay Sievers 			parent = kobject_get(&kobj->kset->kobj);
2310f4dafc0SKay Sievers 		kobj_kset_join(kobj);
2320f4dafc0SKay Sievers 		kobj->parent = parent;
2330f4dafc0SKay Sievers 	}
2340f4dafc0SKay Sievers 
23598406333SThomas Weißschuh 	pr_debug("'%s' (%p): %s: parent: '%s', set: '%s'\n",
236810304dbSHarvey Harrison 		 kobject_name(kobj), kobj, __func__,
2379f66fa2aSGreg Kroah-Hartman 		 parent ? kobject_name(parent) : "<NULL>",
238ce2c9cb0SGreg Kroah-Hartman 		 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
2391da177e4SLinus Torvalds 
24090bc6135SEric W. Biederman 	error = create_dir(kobj);
2411da177e4SLinus Torvalds 	if (error) {
2420f4dafc0SKay Sievers 		kobj_kset_leave(kobj);
2430f4dafc0SKay Sievers 		kobject_put(parent);
2440f4dafc0SKay Sievers 		kobj->parent = NULL;
245dcd0da00SGreg Kroah-Hartman 
246dcd0da00SGreg Kroah-Hartman 		/* be noisy on error issues */
247dcd0da00SGreg Kroah-Hartman 		if (error == -EEXIST)
2483e14c6abSDmitry Vyukov 			pr_err("%s failed for %s with -EEXIST, don't try to register things with the same name in the same directory.\n",
249810304dbSHarvey Harrison 			       __func__, kobject_name(kobj));
250dcd0da00SGreg Kroah-Hartman 		else
2513e14c6abSDmitry Vyukov 			pr_err("%s failed for %s (error: %d parent: %s)\n",
252282029c0SDan Williams 			       __func__, kobject_name(kobj), error,
253282029c0SDan Williams 			       parent ? kobject_name(parent) : "'none'");
2540f4dafc0SKay Sievers 	} else
2550f4dafc0SKay Sievers 		kobj->state_in_sysfs = 1;
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	return error;
2581da177e4SLinus Torvalds }
2591da177e4SLinus Torvalds 
260b592fcfeSEric W. Biederman /**
261ed856349STobin C. Harding  * kobject_set_name_vargs() - Set the name of a kobject.
262663a4743SGreg Kroah-Hartman  * @kobj: struct kobject to set the name of
263663a4743SGreg Kroah-Hartman  * @fmt: format string used to build the name
264663a4743SGreg Kroah-Hartman  * @vargs: vargs to format the string.
265663a4743SGreg Kroah-Hartman  */
kobject_set_name_vargs(struct kobject * kobj,const char * fmt,va_list vargs)2661fa5ae85SKay Sievers int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
267663a4743SGreg Kroah-Hartman 				  va_list vargs)
268663a4743SGreg Kroah-Hartman {
269f773f32dSRasmus Villemoes 	const char *s;
270663a4743SGreg Kroah-Hartman 
2718a577ffcSKay Sievers 	if (kobj->name && !fmt)
2728a577ffcSKay Sievers 		return 0;
2738a577ffcSKay Sievers 
274f773f32dSRasmus Villemoes 	s = kvasprintf_const(GFP_KERNEL, fmt, vargs);
2752abf114fSRasmus Villemoes 	if (!s)
276a4ca6617SKay Sievers 		return -ENOMEM;
277663a4743SGreg Kroah-Hartman 
278f773f32dSRasmus Villemoes 	/*
279f773f32dSRasmus Villemoes 	 * ewww... some of these buggers have '/' in the name ... If
280f773f32dSRasmus Villemoes 	 * that's the case, we need to make sure we have an actual
281f773f32dSRasmus Villemoes 	 * allocated copy to modify, since kvasprintf_const may have
282f773f32dSRasmus Villemoes 	 * returned something from .rodata.
283f773f32dSRasmus Villemoes 	 */
284f773f32dSRasmus Villemoes 	if (strchr(s, '/')) {
285f773f32dSRasmus Villemoes 		char *t;
286f773f32dSRasmus Villemoes 
287f773f32dSRasmus Villemoes 		t = kstrdup(s, GFP_KERNEL);
288f773f32dSRasmus Villemoes 		kfree_const(s);
289f773f32dSRasmus Villemoes 		if (!t)
290f773f32dSRasmus Villemoes 			return -ENOMEM;
291b2f10148SAndy Shevchenko 		s = strreplace(t, '/', '!');
292f773f32dSRasmus Villemoes 	}
293f773f32dSRasmus Villemoes 	kfree_const(kobj->name);
2942abf114fSRasmus Villemoes 	kobj->name = s;
2959f255651SKay Sievers 
296663a4743SGreg Kroah-Hartman 	return 0;
297663a4743SGreg Kroah-Hartman }
2981da177e4SLinus Torvalds 
2991da177e4SLinus Torvalds /**
300ed856349STobin C. Harding  * kobject_set_name() - Set the name of a kobject.
301663a4743SGreg Kroah-Hartman  * @kobj: struct kobject to set the name of
30267be2dd1SMartin Waitz  * @fmt: format string used to build the name
3031da177e4SLinus Torvalds  *
3048c4606b1SGreg Kroah-Hartman  * This sets the name of the kobject.  If you have already added the
3058c4606b1SGreg Kroah-Hartman  * kobject to the system, you must call kobject_rename() in order to
3068c4606b1SGreg Kroah-Hartman  * change the name of the kobject.
3071da177e4SLinus Torvalds  */
kobject_set_name(struct kobject * kobj,const char * fmt,...)3081da177e4SLinus Torvalds int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
3091da177e4SLinus Torvalds {
310a4ca6617SKay Sievers 	va_list vargs;
311663a4743SGreg Kroah-Hartman 	int retval;
3121da177e4SLinus Torvalds 
313a4ca6617SKay Sievers 	va_start(vargs, fmt);
314a4ca6617SKay Sievers 	retval = kobject_set_name_vargs(kobj, fmt, vargs);
315a4ca6617SKay Sievers 	va_end(vargs);
3161da177e4SLinus Torvalds 
317663a4743SGreg Kroah-Hartman 	return retval;
3181da177e4SLinus Torvalds }
3191da177e4SLinus Torvalds EXPORT_SYMBOL(kobject_set_name);
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds /**
322ed856349STobin C. Harding  * kobject_init() - Initialize a kobject structure.
323e86000d0SGreg Kroah-Hartman  * @kobj: pointer to the kobject to initialize
324e86000d0SGreg Kroah-Hartman  * @ktype: pointer to the ktype for this kobject.
325e86000d0SGreg Kroah-Hartman  *
326e86000d0SGreg Kroah-Hartman  * This function will properly initialize a kobject such that it can then
327e86000d0SGreg Kroah-Hartman  * be passed to the kobject_add() call.
328e86000d0SGreg Kroah-Hartman  *
329e86000d0SGreg Kroah-Hartman  * After this function is called, the kobject MUST be cleaned up by a call
330e86000d0SGreg Kroah-Hartman  * to kobject_put(), not by a call to kfree directly to ensure that all of
331e86000d0SGreg Kroah-Hartman  * the memory is cleaned up properly.
332e86000d0SGreg Kroah-Hartman  */
kobject_init(struct kobject * kobj,const struct kobj_type * ktype)333ee6d3dd4SWedson Almeida Filho void kobject_init(struct kobject *kobj, const struct kobj_type *ktype)
334e86000d0SGreg Kroah-Hartman {
335e86000d0SGreg Kroah-Hartman 	char *err_str;
336e86000d0SGreg Kroah-Hartman 
337e86000d0SGreg Kroah-Hartman 	if (!kobj) {
338e86000d0SGreg Kroah-Hartman 		err_str = "invalid kobject pointer!";
339e86000d0SGreg Kroah-Hartman 		goto error;
340e86000d0SGreg Kroah-Hartman 	}
341e86000d0SGreg Kroah-Hartman 	if (!ktype) {
342e86000d0SGreg Kroah-Hartman 		err_str = "must have a ktype to be initialized properly!\n";
343e86000d0SGreg Kroah-Hartman 		goto error;
344e86000d0SGreg Kroah-Hartman 	}
3450f4dafc0SKay Sievers 	if (kobj->state_initialized) {
346e86000d0SGreg Kroah-Hartman 		/* do not error out as sometimes we can recover */
34782d1f117SAndy Shevchenko 		pr_err("kobject (%p): tried to init an initialized object, something is seriously wrong.\n",
34882d1f117SAndy Shevchenko 		       kobj);
34964414da2SThomas Weißschuh 		dump_stack_lvl(KERN_ERR);
350e86000d0SGreg Kroah-Hartman 	}
351e86000d0SGreg Kroah-Hartman 
352a4573c48SGreg Kroah-Hartman 	kobject_init_internal(kobj);
353e86000d0SGreg Kroah-Hartman 	kobj->ktype = ktype;
354e86000d0SGreg Kroah-Hartman 	return;
355e86000d0SGreg Kroah-Hartman 
356e86000d0SGreg Kroah-Hartman error:
35782d1f117SAndy Shevchenko 	pr_err("kobject (%p): %s\n", kobj, err_str);
35864414da2SThomas Weißschuh 	dump_stack_lvl(KERN_ERR);
359e86000d0SGreg Kroah-Hartman }
360f9cb074bSGreg Kroah-Hartman EXPORT_SYMBOL(kobject_init);
361e86000d0SGreg Kroah-Hartman 
kobject_add_varg(struct kobject * kobj,struct kobject * parent,const char * fmt,va_list vargs)3628db14860SNicolas Iooss static __printf(3, 0) int kobject_add_varg(struct kobject *kobj,
3638db14860SNicolas Iooss 					   struct kobject *parent,
364244f6ceeSGreg Kroah-Hartman 					   const char *fmt, va_list vargs)
365244f6ceeSGreg Kroah-Hartman {
366244f6ceeSGreg Kroah-Hartman 	int retval;
367244f6ceeSGreg Kroah-Hartman 
368a4ca6617SKay Sievers 	retval = kobject_set_name_vargs(kobj, fmt, vargs);
369244f6ceeSGreg Kroah-Hartman 	if (retval) {
37098406333SThomas Weißschuh 		pr_err("can not set name properly!\n");
371244f6ceeSGreg Kroah-Hartman 		return retval;
372244f6ceeSGreg Kroah-Hartman 	}
373244f6ceeSGreg Kroah-Hartman 	kobj->parent = parent;
3749e7bbccdSGreg Kroah-Hartman 	return kobject_add_internal(kobj);
375244f6ceeSGreg Kroah-Hartman }
376244f6ceeSGreg Kroah-Hartman 
377244f6ceeSGreg Kroah-Hartman /**
378ed856349STobin C. Harding  * kobject_add() - The main kobject add function.
379244f6ceeSGreg Kroah-Hartman  * @kobj: the kobject to add
380244f6ceeSGreg Kroah-Hartman  * @parent: pointer to the parent of the kobject.
381244f6ceeSGreg Kroah-Hartman  * @fmt: format to name the kobject with.
382244f6ceeSGreg Kroah-Hartman  *
383244f6ceeSGreg Kroah-Hartman  * The kobject name is set and added to the kobject hierarchy in this
384244f6ceeSGreg Kroah-Hartman  * function.
385244f6ceeSGreg Kroah-Hartman  *
386244f6ceeSGreg Kroah-Hartman  * If @parent is set, then the parent of the @kobj will be set to it.
387244f6ceeSGreg Kroah-Hartman  * If @parent is NULL, then the parent of the @kobj will be set to the
3889705710eSBart Van Assche  * kobject associated with the kset assigned to this kobject.  If no kset
389244f6ceeSGreg Kroah-Hartman  * is assigned to the kobject, then the kobject will be located in the
390244f6ceeSGreg Kroah-Hartman  * root of the sysfs tree.
391244f6ceeSGreg Kroah-Hartman  *
3920f4dafc0SKay Sievers  * Note, no "add" uevent will be created with this call, the caller should set
393244f6ceeSGreg Kroah-Hartman  * up all of the necessary sysfs files for the object and then call
394244f6ceeSGreg Kroah-Hartman  * kobject_uevent() with the UEVENT_ADD parameter to ensure that
395244f6ceeSGreg Kroah-Hartman  * userspace is properly notified of this kobject's creation.
39692067f84STobin C. Harding  *
39792067f84STobin C. Harding  * Return: If this function returns an error, kobject_put() must be
39892067f84STobin C. Harding  *         called to properly clean up the memory associated with the
39992067f84STobin C. Harding  *         object.  Under no instance should the kobject that is passed
40092067f84STobin C. Harding  *         to this function be directly freed with a call to kfree(),
40192067f84STobin C. Harding  *         that can leak memory.
40292067f84STobin C. Harding  *
40370e16a62SGreg Kroah-Hartman  *         If this function returns success, kobject_put() must also be called
40470e16a62SGreg Kroah-Hartman  *         in order to properly clean up the memory associated with the object.
40570e16a62SGreg Kroah-Hartman  *
40670e16a62SGreg Kroah-Hartman  *         In short, once this function is called, kobject_put() MUST be called
40770e16a62SGreg Kroah-Hartman  *         when the use of the object is finished in order to properly free
40870e16a62SGreg Kroah-Hartman  *         everything.
409244f6ceeSGreg Kroah-Hartman  */
kobject_add(struct kobject * kobj,struct kobject * parent,const char * fmt,...)410b2d6db58SGreg Kroah-Hartman int kobject_add(struct kobject *kobj, struct kobject *parent,
411244f6ceeSGreg Kroah-Hartman 		const char *fmt, ...)
412244f6ceeSGreg Kroah-Hartman {
413244f6ceeSGreg Kroah-Hartman 	va_list args;
414244f6ceeSGreg Kroah-Hartman 	int retval;
415244f6ceeSGreg Kroah-Hartman 
416244f6ceeSGreg Kroah-Hartman 	if (!kobj)
417244f6ceeSGreg Kroah-Hartman 		return -EINVAL;
418244f6ceeSGreg Kroah-Hartman 
4190f4dafc0SKay Sievers 	if (!kobj->state_initialized) {
42082d1f117SAndy Shevchenko 		pr_err("kobject '%s' (%p): tried to add an uninitialized object, something is seriously wrong.\n",
4210f4dafc0SKay Sievers 		       kobject_name(kobj), kobj);
42264414da2SThomas Weißschuh 		dump_stack_lvl(KERN_ERR);
4230f4dafc0SKay Sievers 		return -EINVAL;
4240f4dafc0SKay Sievers 	}
425244f6ceeSGreg Kroah-Hartman 	va_start(args, fmt);
426244f6ceeSGreg Kroah-Hartman 	retval = kobject_add_varg(kobj, parent, fmt, args);
427244f6ceeSGreg Kroah-Hartman 	va_end(args);
428244f6ceeSGreg Kroah-Hartman 
429244f6ceeSGreg Kroah-Hartman 	return retval;
430244f6ceeSGreg Kroah-Hartman }
431b2d6db58SGreg Kroah-Hartman EXPORT_SYMBOL(kobject_add);
432244f6ceeSGreg Kroah-Hartman 
433e86000d0SGreg Kroah-Hartman /**
434ed856349STobin C. Harding  * kobject_init_and_add() - Initialize a kobject structure and add it to
435ed856349STobin C. Harding  *                          the kobject hierarchy.
436c11c4154SGreg Kroah-Hartman  * @kobj: pointer to the kobject to initialize
437c11c4154SGreg Kroah-Hartman  * @ktype: pointer to the ktype for this kobject.
438c11c4154SGreg Kroah-Hartman  * @parent: pointer to the parent of this kobject.
439c11c4154SGreg Kroah-Hartman  * @fmt: the name of the kobject.
440c11c4154SGreg Kroah-Hartman  *
4411fd7c3b4STobin C. Harding  * This function combines the call to kobject_init() and kobject_add().
4421fd7c3b4STobin C. Harding  *
4431fd7c3b4STobin C. Harding  * If this function returns an error, kobject_put() must be called to
4441fd7c3b4STobin C. Harding  * properly clean up the memory associated with the object.  This is the
4451fd7c3b4STobin C. Harding  * same type of error handling after a call to kobject_add() and kobject
4461fd7c3b4STobin C. Harding  * lifetime rules are the same here.
447c11c4154SGreg Kroah-Hartman  */
kobject_init_and_add(struct kobject * kobj,const struct kobj_type * ktype,struct kobject * parent,const char * fmt,...)448ee6d3dd4SWedson Almeida Filho int kobject_init_and_add(struct kobject *kobj, const struct kobj_type *ktype,
449c11c4154SGreg Kroah-Hartman 			 struct kobject *parent, const char *fmt, ...)
450c11c4154SGreg Kroah-Hartman {
451c11c4154SGreg Kroah-Hartman 	va_list args;
452c11c4154SGreg Kroah-Hartman 	int retval;
453c11c4154SGreg Kroah-Hartman 
454f9cb074bSGreg Kroah-Hartman 	kobject_init(kobj, ktype);
455c11c4154SGreg Kroah-Hartman 
456c11c4154SGreg Kroah-Hartman 	va_start(args, fmt);
457c11c4154SGreg Kroah-Hartman 	retval = kobject_add_varg(kobj, parent, fmt, args);
458c11c4154SGreg Kroah-Hartman 	va_end(args);
459c11c4154SGreg Kroah-Hartman 
460c11c4154SGreg Kroah-Hartman 	return retval;
461c11c4154SGreg Kroah-Hartman }
462c11c4154SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(kobject_init_and_add);
463c11c4154SGreg Kroah-Hartman 
464c11c4154SGreg Kroah-Hartman /**
465ed856349STobin C. Harding  * kobject_rename() - Change the name of an object.
4661da177e4SLinus Torvalds  * @kobj: object in question.
4671da177e4SLinus Torvalds  * @new_name: object's new name
468030c1d2bSEric W. Biederman  *
469030c1d2bSEric W. Biederman  * It is the responsibility of the caller to provide mutual
470030c1d2bSEric W. Biederman  * exclusion between two different calls of kobject_rename
471030c1d2bSEric W. Biederman  * on the same kobject and to ensure that new_name is valid and
472030c1d2bSEric W. Biederman  * won't conflict with other kobjects.
4731da177e4SLinus Torvalds  */
kobject_rename(struct kobject * kobj,const char * new_name)474f3b4f3c6SDmitry Torokhov int kobject_rename(struct kobject *kobj, const char *new_name)
4751da177e4SLinus Torvalds {
4761da177e4SLinus Torvalds 	int error = 0;
477ca2f37dbSJean Tourrilhes 	const char *devpath = NULL;
4780b4a4feaSEric W. Biederman 	const char *dup_name = NULL, *name;
479ca2f37dbSJean Tourrilhes 	char *devpath_string = NULL;
480ca2f37dbSJean Tourrilhes 	char *envp[2];
4811da177e4SLinus Torvalds 
4821da177e4SLinus Torvalds 	kobj = kobject_get(kobj);
4831da177e4SLinus Torvalds 	if (!kobj)
4841da177e4SLinus Torvalds 		return -EINVAL;
485122f8ec7SLin Yi 	if (!kobj->parent) {
486122f8ec7SLin Yi 		kobject_put(kobj);
487b592fcfeSEric W. Biederman 		return -EINVAL;
488122f8ec7SLin Yi 	}
489ca2f37dbSJean Tourrilhes 
490ca2f37dbSJean Tourrilhes 	devpath = kobject_get_path(kobj, GFP_KERNEL);
491ca2f37dbSJean Tourrilhes 	if (!devpath) {
492ca2f37dbSJean Tourrilhes 		error = -ENOMEM;
493ca2f37dbSJean Tourrilhes 		goto out;
494ca2f37dbSJean Tourrilhes 	}
495ca2f37dbSJean Tourrilhes 	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
496ca2f37dbSJean Tourrilhes 	if (!devpath_string) {
497ca2f37dbSJean Tourrilhes 		error = -ENOMEM;
498ca2f37dbSJean Tourrilhes 		goto out;
499ca2f37dbSJean Tourrilhes 	}
500ca2f37dbSJean Tourrilhes 	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
501ca2f37dbSJean Tourrilhes 	envp[0] = devpath_string;
502ca2f37dbSJean Tourrilhes 	envp[1] = NULL;
503ca2f37dbSJean Tourrilhes 
504f773f32dSRasmus Villemoes 	name = dup_name = kstrdup_const(new_name, GFP_KERNEL);
5050b4a4feaSEric W. Biederman 	if (!name) {
5060b4a4feaSEric W. Biederman 		error = -ENOMEM;
5070b4a4feaSEric W. Biederman 		goto out;
5080b4a4feaSEric W. Biederman 	}
5090b4a4feaSEric W. Biederman 
510e34ff490STejun Heo 	error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj));
5110b4a4feaSEric W. Biederman 	if (error)
5120b4a4feaSEric W. Biederman 		goto out;
5130b4a4feaSEric W. Biederman 
5140b4a4feaSEric W. Biederman 	/* Install the new kobject name */
5150b4a4feaSEric W. Biederman 	dup_name = kobj->name;
5160b4a4feaSEric W. Biederman 	kobj->name = name;
517ca2f37dbSJean Tourrilhes 
518ca2f37dbSJean Tourrilhes 	/* This function is mostly/only used for network interface.
519ca2f37dbSJean Tourrilhes 	 * Some hotplug package track interfaces by their name and
520ca2f37dbSJean Tourrilhes 	 * therefore want to know when the name is changed by the user. */
521ca2f37dbSJean Tourrilhes 	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
522ca2f37dbSJean Tourrilhes 
523ca2f37dbSJean Tourrilhes out:
524f773f32dSRasmus Villemoes 	kfree_const(dup_name);
525ca2f37dbSJean Tourrilhes 	kfree(devpath_string);
526ca2f37dbSJean Tourrilhes 	kfree(devpath);
527b592fcfeSEric W. Biederman 	kobject_put(kobj);
528b592fcfeSEric W. Biederman 
529b592fcfeSEric W. Biederman 	return error;
530b592fcfeSEric W. Biederman }
5318344b568SAlex Chiang EXPORT_SYMBOL_GPL(kobject_rename);
532b592fcfeSEric W. Biederman 
533b592fcfeSEric W. Biederman /**
534ed856349STobin C. Harding  * kobject_move() - Move object to another parent.
5358a82472fSCornelia Huck  * @kobj: object in question.
536c744aeaeSCornelia Huck  * @new_parent: object's new parent (can be NULL)
5378a82472fSCornelia Huck  */
kobject_move(struct kobject * kobj,struct kobject * new_parent)5388a82472fSCornelia Huck int kobject_move(struct kobject *kobj, struct kobject *new_parent)
5398a82472fSCornelia Huck {
5408a82472fSCornelia Huck 	int error;
5418a82472fSCornelia Huck 	struct kobject *old_parent;
5428a82472fSCornelia Huck 	const char *devpath = NULL;
5438a82472fSCornelia Huck 	char *devpath_string = NULL;
5448a82472fSCornelia Huck 	char *envp[2];
5458a82472fSCornelia Huck 
5468a82472fSCornelia Huck 	kobj = kobject_get(kobj);
5478a82472fSCornelia Huck 	if (!kobj)
5488a82472fSCornelia Huck 		return -EINVAL;
5498a82472fSCornelia Huck 	new_parent = kobject_get(new_parent);
5508a82472fSCornelia Huck 	if (!new_parent) {
551c744aeaeSCornelia Huck 		if (kobj->kset)
552c744aeaeSCornelia Huck 			new_parent = kobject_get(&kobj->kset->kobj);
5538a82472fSCornelia Huck 	}
554e34ff490STejun Heo 
5558a82472fSCornelia Huck 	/* old object path */
5568a82472fSCornelia Huck 	devpath = kobject_get_path(kobj, GFP_KERNEL);
5578a82472fSCornelia Huck 	if (!devpath) {
5588a82472fSCornelia Huck 		error = -ENOMEM;
5598a82472fSCornelia Huck 		goto out;
5608a82472fSCornelia Huck 	}
5618a82472fSCornelia Huck 	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
5628a82472fSCornelia Huck 	if (!devpath_string) {
5638a82472fSCornelia Huck 		error = -ENOMEM;
5648a82472fSCornelia Huck 		goto out;
5658a82472fSCornelia Huck 	}
5668a82472fSCornelia Huck 	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
5678a82472fSCornelia Huck 	envp[0] = devpath_string;
5688a82472fSCornelia Huck 	envp[1] = NULL;
569e34ff490STejun Heo 	error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj));
5708a82472fSCornelia Huck 	if (error)
5718a82472fSCornelia Huck 		goto out;
5728a82472fSCornelia Huck 	old_parent = kobj->parent;
5738a82472fSCornelia Huck 	kobj->parent = new_parent;
5749e993efbSDmitriy Monakhov 	new_parent = NULL;
5758a82472fSCornelia Huck 	kobject_put(old_parent);
5768a82472fSCornelia Huck 	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
5778a82472fSCornelia Huck out:
5789e993efbSDmitriy Monakhov 	kobject_put(new_parent);
5798a82472fSCornelia Huck 	kobject_put(kobj);
5808a82472fSCornelia Huck 	kfree(devpath_string);
5818a82472fSCornelia Huck 	kfree(devpath);
5828a82472fSCornelia Huck 	return error;
5838a82472fSCornelia Huck }
58424199d20SAnand Jain EXPORT_SYMBOL_GPL(kobject_move);
5858a82472fSCornelia Huck 
__kobject_del(struct kobject * kobj)586079ad2fbSHeikki Krogerus static void __kobject_del(struct kobject *kobj)
5871da177e4SLinus Torvalds {
588324a56e1STejun Heo 	struct kernfs_node *sd;
5893d378dc7SColin Ian King 	const struct kobj_type *ktype;
59026ea12deSTejun Heo 
59126ea12deSTejun Heo 	sd = kobj->sd;
5923d378dc7SColin Ian King 	ktype = get_ktype(kobj);
593aa30f47cSKimberly Brown 
594*7f414d30SGreg Kroah-Hartman 	if (ktype)
595aa30f47cSKimberly Brown 		sysfs_remove_groups(kobj, ktype->default_groups);
596aa30f47cSKimberly Brown 
5970e5596c5SGreg Kroah-Hartman 	/* send "remove" if the caller did not do it but sent "add" */
5980e5596c5SGreg Kroah-Hartman 	if (kobj->state_add_uevent_sent && !kobj->state_remove_uevent_sent) {
59998406333SThomas Weißschuh 		pr_debug("'%s' (%p): auto cleanup 'remove' event\n",
6000e5596c5SGreg Kroah-Hartman 			 kobject_name(kobj), kobj);
6010e5596c5SGreg Kroah-Hartman 		kobject_uevent(kobj, KOBJ_REMOVE);
6020e5596c5SGreg Kroah-Hartman 	}
6030e5596c5SGreg Kroah-Hartman 
6041da177e4SLinus Torvalds 	sysfs_remove_dir(kobj);
60526ea12deSTejun Heo 	sysfs_put(sd);
60626ea12deSTejun Heo 
6070f4dafc0SKay Sievers 	kobj->state_in_sysfs = 0;
6080f4dafc0SKay Sievers 	kobj_kset_leave(kobj);
6090f4dafc0SKay Sievers 	kobj->parent = NULL;
6101da177e4SLinus Torvalds }
611079ad2fbSHeikki Krogerus 
612079ad2fbSHeikki Krogerus /**
613079ad2fbSHeikki Krogerus  * kobject_del() - Unlink kobject from hierarchy.
614079ad2fbSHeikki Krogerus  * @kobj: object.
615079ad2fbSHeikki Krogerus  *
616079ad2fbSHeikki Krogerus  * This is the function that should be called to delete an object
617079ad2fbSHeikki Krogerus  * successfully added via kobject_add().
618079ad2fbSHeikki Krogerus  */
kobject_del(struct kobject * kobj)619079ad2fbSHeikki Krogerus void kobject_del(struct kobject *kobj)
620079ad2fbSHeikki Krogerus {
62140b8b826SAndy Shevchenko 	struct kobject *parent;
622079ad2fbSHeikki Krogerus 
62340b8b826SAndy Shevchenko 	if (!kobj)
62440b8b826SAndy Shevchenko 		return;
62540b8b826SAndy Shevchenko 
62640b8b826SAndy Shevchenko 	parent = kobj->parent;
627079ad2fbSHeikki Krogerus 	__kobject_del(kobj);
628079ad2fbSHeikki Krogerus 	kobject_put(parent);
629079ad2fbSHeikki Krogerus }
630fa40ae34SGabriel Somlo EXPORT_SYMBOL(kobject_del);
6311da177e4SLinus Torvalds 
6321da177e4SLinus Torvalds /**
633ed856349STobin C. Harding  * kobject_get() - Increment refcount for object.
6341da177e4SLinus Torvalds  * @kobj: object.
6351da177e4SLinus Torvalds  */
kobject_get(struct kobject * kobj)6361da177e4SLinus Torvalds struct kobject *kobject_get(struct kobject *kobj)
6371da177e4SLinus Torvalds {
638d82d54afSEthan Zhao 	if (kobj) {
639d82d54afSEthan Zhao 		if (!kobj->state_initialized)
64082d1f117SAndy Shevchenko 			WARN(1, KERN_WARNING
64182d1f117SAndy Shevchenko 				"kobject: '%s' (%p): is not initialized, yet kobject_get() is being called.\n",
64282d1f117SAndy Shevchenko 			     kobject_name(kobj), kobj);
6431da177e4SLinus Torvalds 		kref_get(&kobj->kref);
644d82d54afSEthan Zhao 	}
6451da177e4SLinus Torvalds 	return kobj;
6461da177e4SLinus Torvalds }
647fa40ae34SGabriel Somlo EXPORT_SYMBOL(kobject_get);
6481da177e4SLinus Torvalds 
kobject_get_unless_zero(struct kobject * kobj)649c70c176fSJan Kara struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
650a49b7e82SLinus Torvalds {
651c70c176fSJan Kara 	if (!kobj)
652c70c176fSJan Kara 		return NULL;
653a49b7e82SLinus Torvalds 	if (!kref_get_unless_zero(&kobj->kref))
654a49b7e82SLinus Torvalds 		kobj = NULL;
655a49b7e82SLinus Torvalds 	return kobj;
656a49b7e82SLinus Torvalds }
657c70c176fSJan Kara EXPORT_SYMBOL(kobject_get_unless_zero);
658a49b7e82SLinus Torvalds 
65918041f47SGreg Kroah-Hartman /*
6601da177e4SLinus Torvalds  * kobject_cleanup - free kobject resources.
66118041f47SGreg Kroah-Hartman  * @kobj: object to cleanup
6621da177e4SLinus Torvalds  */
kobject_cleanup(struct kobject * kobj)66318041f47SGreg Kroah-Hartman static void kobject_cleanup(struct kobject *kobj)
6641da177e4SLinus Torvalds {
665079ad2fbSHeikki Krogerus 	struct kobject *parent = kobj->parent;
666ee6d3dd4SWedson Almeida Filho 	const struct kobj_type *t = get_ktype(kobj);
667af5ca3f4SKay Sievers 	const char *name = kobj->name;
6681da177e4SLinus Torvalds 
66998406333SThomas Weißschuh 	pr_debug("'%s' (%p): %s, parent %p\n",
670c817a67eSRussell King 		 kobject_name(kobj), kobj, __func__, kobj->parent);
6710f4dafc0SKay Sievers 
672*7f414d30SGreg Kroah-Hartman 	if (t && !t->release)
673*7f414d30SGreg Kroah-Hartman 		pr_debug("'%s' (%p): does not have a release() function, it is broken and must be fixed. See Documentation/core-api/kobject.rst.\n",
674*7f414d30SGreg Kroah-Hartman 			 kobject_name(kobj), kobj);
675*7f414d30SGreg Kroah-Hartman 
6760f4dafc0SKay Sievers 	/* remove from sysfs if the caller did not do it */
6770f4dafc0SKay Sievers 	if (kobj->state_in_sysfs) {
67898406333SThomas Weißschuh 		pr_debug("'%s' (%p): auto cleanup kobject_del\n",
6790f4dafc0SKay Sievers 			 kobject_name(kobj), kobj);
680079ad2fbSHeikki Krogerus 		__kobject_del(kobj);
681079ad2fbSHeikki Krogerus 	} else {
682079ad2fbSHeikki Krogerus 		/* avoid dropping the parent reference unnecessarily */
683079ad2fbSHeikki Krogerus 		parent = NULL;
6840f4dafc0SKay Sievers 	}
6850f4dafc0SKay Sievers 
686*7f414d30SGreg Kroah-Hartman 	if (t && t->release) {
68798406333SThomas Weißschuh 		pr_debug("'%s' (%p): calling ktype release\n",
6880f4dafc0SKay Sievers 			 kobject_name(kobj), kobj);
6891da177e4SLinus Torvalds 		t->release(kobj);
6900f4dafc0SKay Sievers 	}
6910f4dafc0SKay Sievers 
6920f4dafc0SKay Sievers 	/* free name if we allocated it */
693af5ca3f4SKay Sievers 	if (name) {
69498406333SThomas Weißschuh 		pr_debug("'%s': free name\n", name);
695f773f32dSRasmus Villemoes 		kfree_const(name);
696ce2c9cb0SGreg Kroah-Hartman 	}
697079ad2fbSHeikki Krogerus 
698079ad2fbSHeikki Krogerus 	kobject_put(parent);
6991da177e4SLinus Torvalds }
7001da177e4SLinus Torvalds 
701c817a67eSRussell King #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
kobject_delayed_cleanup(struct work_struct * work)702c817a67eSRussell King static void kobject_delayed_cleanup(struct work_struct *work)
703c817a67eSRussell King {
704c817a67eSRussell King 	kobject_cleanup(container_of(to_delayed_work(work),
705c817a67eSRussell King 				     struct kobject, release));
706c817a67eSRussell King }
707c817a67eSRussell King #endif
708c817a67eSRussell King 
kobject_release(struct kref * kref)7091da177e4SLinus Torvalds static void kobject_release(struct kref *kref)
7101da177e4SLinus Torvalds {
711c817a67eSRussell King 	struct kobject *kobj = container_of(kref, struct kobject, kref);
712c817a67eSRussell King #ifdef CONFIG_DEBUG_KOBJECT_RELEASE
7138032bf12SJason A. Donenfeld 	unsigned long delay = HZ + HZ * get_random_u32_below(4);
71498406333SThomas Weißschuh 	pr_info("'%s' (%p): %s, parent %p (delayed %ld)\n",
71589c86a64SBjorn Helgaas 		kobject_name(kobj), kobj, __func__, kobj->parent, delay);
716c817a67eSRussell King 	INIT_DELAYED_WORK(&kobj->release, kobject_delayed_cleanup);
71789c86a64SBjorn Helgaas 
71889c86a64SBjorn Helgaas 	schedule_delayed_work(&kobj->release, delay);
719c817a67eSRussell King #else
720c817a67eSRussell King 	kobject_cleanup(kobj);
721c817a67eSRussell King #endif
7221da177e4SLinus Torvalds }
7231da177e4SLinus Torvalds 
7241da177e4SLinus Torvalds /**
725ed856349STobin C. Harding  * kobject_put() - Decrement refcount for object.
7261da177e4SLinus Torvalds  * @kobj: object.
7271da177e4SLinus Torvalds  *
7281da177e4SLinus Torvalds  * Decrement the refcount, and if 0, call kobject_cleanup().
7291da177e4SLinus Torvalds  */
kobject_put(struct kobject * kobj)7301da177e4SLinus Torvalds void kobject_put(struct kobject *kobj)
7311da177e4SLinus Torvalds {
732c1ebdae5SGreg Kroah-Hartman 	if (kobj) {
733d955c78aSArjan van de Ven 		if (!kobj->state_initialized)
73482d1f117SAndy Shevchenko 			WARN(1, KERN_WARNING
73582d1f117SAndy Shevchenko 				"kobject: '%s' (%p): is not initialized, yet kobject_put() is being called.\n",
73682d1f117SAndy Shevchenko 			     kobject_name(kobj), kobj);
7371da177e4SLinus Torvalds 		kref_put(&kobj->kref, kobject_release);
7381da177e4SLinus Torvalds 	}
739c1ebdae5SGreg Kroah-Hartman }
740fa40ae34SGabriel Somlo EXPORT_SYMBOL(kobject_put);
7411da177e4SLinus Torvalds 
dynamic_kobj_release(struct kobject * kobj)7423f9e3ee9SGreg Kroah-Hartman static void dynamic_kobj_release(struct kobject *kobj)
7437423172aSJun'ichi Nomura {
74498406333SThomas Weißschuh 	pr_debug("(%p): %s\n", kobj, __func__);
7457423172aSJun'ichi Nomura 	kfree(kobj);
7467423172aSJun'ichi Nomura }
7477423172aSJun'ichi Nomura 
748dda6b81fSThomas Weißschuh static const struct kobj_type dynamic_kobj_ktype = {
7493f9e3ee9SGreg Kroah-Hartman 	.release	= dynamic_kobj_release,
750386f275fSKay Sievers 	.sysfs_ops	= &kobj_sysfs_ops,
7517423172aSJun'ichi Nomura };
7527423172aSJun'ichi Nomura 
75343968d2fSGreg Kroah-Hartman /**
754ed856349STobin C. Harding  * kobject_create() - Create a struct kobject dynamically.
7553f9e3ee9SGreg Kroah-Hartman  *
7563f9e3ee9SGreg Kroah-Hartman  * This function creates a kobject structure dynamically and sets it up
7573f9e3ee9SGreg Kroah-Hartman  * to be a "dynamic" kobject with a default release function set up.
7583f9e3ee9SGreg Kroah-Hartman  *
7593f9e3ee9SGreg Kroah-Hartman  * If the kobject was not able to be created, NULL will be returned.
76043968d2fSGreg Kroah-Hartman  * The kobject structure returned from here must be cleaned up with a
761f9cb074bSGreg Kroah-Hartman  * call to kobject_put() and not kfree(), as kobject_init() has
76243968d2fSGreg Kroah-Hartman  * already been called on this structure.
7633f9e3ee9SGreg Kroah-Hartman  */
kobject_create(void)7648988bacdSQu Wenruo static struct kobject *kobject_create(void)
7653f9e3ee9SGreg Kroah-Hartman {
7663f9e3ee9SGreg Kroah-Hartman 	struct kobject *kobj;
7673f9e3ee9SGreg Kroah-Hartman 
7683f9e3ee9SGreg Kroah-Hartman 	kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
7693f9e3ee9SGreg Kroah-Hartman 	if (!kobj)
7703f9e3ee9SGreg Kroah-Hartman 		return NULL;
7713f9e3ee9SGreg Kroah-Hartman 
772f9cb074bSGreg Kroah-Hartman 	kobject_init(kobj, &dynamic_kobj_ktype);
7733f9e3ee9SGreg Kroah-Hartman 	return kobj;
7743f9e3ee9SGreg Kroah-Hartman }
7753f9e3ee9SGreg Kroah-Hartman 
7763f9e3ee9SGreg Kroah-Hartman /**
777ed856349STobin C. Harding  * kobject_create_and_add() - Create a struct kobject dynamically and
778ed856349STobin C. Harding  *                            register it with sysfs.
7799ff1f838SZhi Yong Wu  * @name: the name for the kobject
7803f9e3ee9SGreg Kroah-Hartman  * @parent: the parent kobject of this kobject, if any.
7813f9e3ee9SGreg Kroah-Hartman  *
782f70701a3SDave Young  * This function creates a kobject structure dynamically and registers it
7833f9e3ee9SGreg Kroah-Hartman  * with sysfs.  When you are finished with this structure, call
78478a2d906SGreg Kroah-Hartman  * kobject_put() and the structure will be dynamically freed when
7853f9e3ee9SGreg Kroah-Hartman  * it is no longer being used.
7863f9e3ee9SGreg Kroah-Hartman  *
7873f9e3ee9SGreg Kroah-Hartman  * If the kobject was not able to be created, NULL will be returned.
7883f9e3ee9SGreg Kroah-Hartman  */
kobject_create_and_add(const char * name,struct kobject * parent)7893f9e3ee9SGreg Kroah-Hartman struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
7903f9e3ee9SGreg Kroah-Hartman {
7913f9e3ee9SGreg Kroah-Hartman 	struct kobject *kobj;
7923f9e3ee9SGreg Kroah-Hartman 	int retval;
7933f9e3ee9SGreg Kroah-Hartman 
7943f9e3ee9SGreg Kroah-Hartman 	kobj = kobject_create();
7953f9e3ee9SGreg Kroah-Hartman 	if (!kobj)
7963f9e3ee9SGreg Kroah-Hartman 		return NULL;
7973f9e3ee9SGreg Kroah-Hartman 
798b2d6db58SGreg Kroah-Hartman 	retval = kobject_add(kobj, parent, "%s", name);
7993f9e3ee9SGreg Kroah-Hartman 	if (retval) {
80082d1f117SAndy Shevchenko 		pr_warn("%s: kobject_add error: %d\n", __func__, retval);
8013f9e3ee9SGreg Kroah-Hartman 		kobject_put(kobj);
8023f9e3ee9SGreg Kroah-Hartman 		kobj = NULL;
8033f9e3ee9SGreg Kroah-Hartman 	}
8043f9e3ee9SGreg Kroah-Hartman 	return kobj;
8053f9e3ee9SGreg Kroah-Hartman }
8063f9e3ee9SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(kobject_create_and_add);
8073f9e3ee9SGreg Kroah-Hartman 
8087423172aSJun'ichi Nomura /**
809ed856349STobin C. Harding  * kset_init() - Initialize a kset for use.
8101da177e4SLinus Torvalds  * @k: kset
8111da177e4SLinus Torvalds  */
kset_init(struct kset * k)8121da177e4SLinus Torvalds void kset_init(struct kset *k)
8131da177e4SLinus Torvalds {
814e1543ddfSGreg Kroah-Hartman 	kobject_init_internal(&k->kobj);
8151da177e4SLinus Torvalds 	INIT_LIST_HEAD(&k->list);
8161da177e4SLinus Torvalds 	spin_lock_init(&k->list_lock);
8171da177e4SLinus Torvalds }
8181da177e4SLinus Torvalds 
81923b5212cSKay Sievers /* default kobject attribute operations */
kobj_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)82023b5212cSKay Sievers static ssize_t kobj_attr_show(struct kobject *kobj, struct attribute *attr,
82123b5212cSKay Sievers 			      char *buf)
82223b5212cSKay Sievers {
82323b5212cSKay Sievers 	struct kobj_attribute *kattr;
82423b5212cSKay Sievers 	ssize_t ret = -EIO;
82523b5212cSKay Sievers 
82623b5212cSKay Sievers 	kattr = container_of(attr, struct kobj_attribute, attr);
82723b5212cSKay Sievers 	if (kattr->show)
82823b5212cSKay Sievers 		ret = kattr->show(kobj, kattr, buf);
82923b5212cSKay Sievers 	return ret;
83023b5212cSKay Sievers }
83123b5212cSKay Sievers 
kobj_attr_store(struct kobject * kobj,struct attribute * attr,const char * buf,size_t count)83223b5212cSKay Sievers static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
83323b5212cSKay Sievers 			       const char *buf, size_t count)
83423b5212cSKay Sievers {
83523b5212cSKay Sievers 	struct kobj_attribute *kattr;
83623b5212cSKay Sievers 	ssize_t ret = -EIO;
83723b5212cSKay Sievers 
83823b5212cSKay Sievers 	kattr = container_of(attr, struct kobj_attribute, attr);
83923b5212cSKay Sievers 	if (kattr->store)
84023b5212cSKay Sievers 		ret = kattr->store(kobj, kattr, buf, count);
84123b5212cSKay Sievers 	return ret;
84223b5212cSKay Sievers }
84323b5212cSKay Sievers 
84452cf25d0SEmese Revfy const struct sysfs_ops kobj_sysfs_ops = {
84523b5212cSKay Sievers 	.show	= kobj_attr_show,
84623b5212cSKay Sievers 	.store	= kobj_attr_store,
84723b5212cSKay Sievers };
84829dfe2dcSJeff Mahoney EXPORT_SYMBOL_GPL(kobj_sysfs_ops);
8491da177e4SLinus Torvalds 
8501da177e4SLinus Torvalds /**
851ed856349STobin C. Harding  * kset_register() - Initialize and add a kset.
8521da177e4SLinus Torvalds  * @k: kset.
8531662cea4SYang Yingliang  *
8541662cea4SYang Yingliang  * NOTE: On error, the kset.kobj.name allocated by() kobj_set_name()
8551662cea4SYang Yingliang  * is freed, it can not be used any more.
8561da177e4SLinus Torvalds  */
kset_register(struct kset * k)8571da177e4SLinus Torvalds int kset_register(struct kset *k)
8581da177e4SLinus Torvalds {
85980f03e34SKay Sievers 	int err;
86080f03e34SKay Sievers 
86131b9025aSGreg Kroah-Hartman 	if (!k)
86231b9025aSGreg Kroah-Hartman 		return -EINVAL;
86380f03e34SKay Sievers 
8644d0fe8c5SZhen Lei 	if (!k->kobj.ktype) {
8654d0fe8c5SZhen Lei 		pr_err("must have a ktype to be initialized properly!\n");
8664d0fe8c5SZhen Lei 		return -EINVAL;
8674d0fe8c5SZhen Lei 	}
8684d0fe8c5SZhen Lei 
8691da177e4SLinus Torvalds 	kset_init(k);
87012e339acSGreg Kroah-Hartman 	err = kobject_add_internal(&k->kobj);
8711662cea4SYang Yingliang 	if (err) {
8721662cea4SYang Yingliang 		kfree_const(k->kobj.name);
8731662cea4SYang Yingliang 		/* Set it to NULL to avoid accessing bad pointer in callers. */
8741662cea4SYang Yingliang 		k->kobj.name = NULL;
87580f03e34SKay Sievers 		return err;
8761662cea4SYang Yingliang 	}
87780f03e34SKay Sievers 	kobject_uevent(&k->kobj, KOBJ_ADD);
87880f03e34SKay Sievers 	return 0;
8791da177e4SLinus Torvalds }
880fa40ae34SGabriel Somlo EXPORT_SYMBOL(kset_register);
8811da177e4SLinus Torvalds 
8821da177e4SLinus Torvalds /**
883ed856349STobin C. Harding  * kset_unregister() - Remove a kset.
8841da177e4SLinus Torvalds  * @k: kset.
8851da177e4SLinus Torvalds  */
kset_unregister(struct kset * k)8861da177e4SLinus Torvalds void kset_unregister(struct kset *k)
8871da177e4SLinus Torvalds {
88831b9025aSGreg Kroah-Hartman 	if (!k)
88931b9025aSGreg Kroah-Hartman 		return;
89035a5fe69SBjorn Helgaas 	kobject_del(&k->kobj);
89178a2d906SGreg Kroah-Hartman 	kobject_put(&k->kobj);
8921da177e4SLinus Torvalds }
893fa40ae34SGabriel Somlo EXPORT_SYMBOL(kset_unregister);
8941da177e4SLinus Torvalds 
8951da177e4SLinus Torvalds /**
896ed856349STobin C. Harding  * kset_find_obj() - Search for object in kset.
8971da177e4SLinus Torvalds  * @kset: kset we're looking in.
8981da177e4SLinus Torvalds  * @name: object's name.
8991da177e4SLinus Torvalds  *
9001da177e4SLinus Torvalds  * Lock kset via @kset->subsys, and iterate over @kset->list,
9011da177e4SLinus Torvalds  * looking for a matching kobject. If matching object is found
9021da177e4SLinus Torvalds  * take a reference and return the object.
9031da177e4SLinus Torvalds  */
kset_find_obj(struct kset * kset,const char * name)9041da177e4SLinus Torvalds struct kobject *kset_find_obj(struct kset *kset, const char *name)
9051da177e4SLinus Torvalds {
906c6a2a3dcSRobert P. J. Day 	struct kobject *k;
9071da177e4SLinus Torvalds 	struct kobject *ret = NULL;
9081da177e4SLinus Torvalds 
9091da177e4SLinus Torvalds 	spin_lock(&kset->list_lock);
910c25d1dfbSRobin Holt 
911c6a2a3dcSRobert P. J. Day 	list_for_each_entry(k, &kset->list, entry) {
9121da177e4SLinus Torvalds 		if (kobject_name(k) && !strcmp(kobject_name(k), name)) {
913a49b7e82SLinus Torvalds 			ret = kobject_get_unless_zero(k);
9141da177e4SLinus Torvalds 			break;
9151da177e4SLinus Torvalds 		}
9161da177e4SLinus Torvalds 	}
917c25d1dfbSRobin Holt 
9181da177e4SLinus Torvalds 	spin_unlock(&kset->list_lock);
9191da177e4SLinus Torvalds 	return ret;
9201da177e4SLinus Torvalds }
9212fe829acSGabriel Somlo EXPORT_SYMBOL_GPL(kset_find_obj);
9221da177e4SLinus Torvalds 
kset_release(struct kobject * kobj)923b727c702SGreg Kroah-Hartman static void kset_release(struct kobject *kobj)
924b727c702SGreg Kroah-Hartman {
925b727c702SGreg Kroah-Hartman 	struct kset *kset = container_of(kobj, struct kset, kobj);
92698406333SThomas Weißschuh 	pr_debug("'%s' (%p): %s\n",
927810304dbSHarvey Harrison 		 kobject_name(kobj), kobj, __func__);
928b727c702SGreg Kroah-Hartman 	kfree(kset);
929b727c702SGreg Kroah-Hartman }
930b727c702SGreg Kroah-Hartman 
kset_get_ownership(const struct kobject * kobj,kuid_t * uid,kgid_t * gid)93102a476d9SGreg Kroah-Hartman static void kset_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
932d028b6f7SDmitry Torokhov {
933d028b6f7SDmitry Torokhov 	if (kobj->parent)
934d028b6f7SDmitry Torokhov 		kobject_get_ownership(kobj->parent, uid, gid);
935d028b6f7SDmitry Torokhov }
936d028b6f7SDmitry Torokhov 
937dda6b81fSThomas Weißschuh static const struct kobj_type kset_ktype = {
938386f275fSKay Sievers 	.sysfs_ops	= &kobj_sysfs_ops,
939b727c702SGreg Kroah-Hartman 	.release	= kset_release,
940d028b6f7SDmitry Torokhov 	.get_ownership	= kset_get_ownership,
941b727c702SGreg Kroah-Hartman };
942b727c702SGreg Kroah-Hartman 
943b727c702SGreg Kroah-Hartman /**
944ed856349STobin C. Harding  * kset_create() - Create a struct kset dynamically.
945b727c702SGreg Kroah-Hartman  *
946b727c702SGreg Kroah-Hartman  * @name: the name for the kset
947b727c702SGreg Kroah-Hartman  * @uevent_ops: a struct kset_uevent_ops for the kset
948b727c702SGreg Kroah-Hartman  * @parent_kobj: the parent kobject of this kset, if any.
949b727c702SGreg Kroah-Hartman  *
950b727c702SGreg Kroah-Hartman  * This function creates a kset structure dynamically.  This structure can
951b727c702SGreg Kroah-Hartman  * then be registered with the system and show up in sysfs with a call to
952b727c702SGreg Kroah-Hartman  * kset_register().  When you are finished with this structure, if
953b727c702SGreg Kroah-Hartman  * kset_register() has been called, call kset_unregister() and the
954b727c702SGreg Kroah-Hartman  * structure will be dynamically freed when it is no longer being used.
955b727c702SGreg Kroah-Hartman  *
956b727c702SGreg Kroah-Hartman  * If the kset was not able to be created, NULL will be returned.
957b727c702SGreg Kroah-Hartman  */
kset_create(const char * name,const struct kset_uevent_ops * uevent_ops,struct kobject * parent_kobj)958b727c702SGreg Kroah-Hartman static struct kset *kset_create(const char *name,
9599cd43611SEmese Revfy 				const struct kset_uevent_ops *uevent_ops,
960b727c702SGreg Kroah-Hartman 				struct kobject *parent_kobj)
961b727c702SGreg Kroah-Hartman {
962b727c702SGreg Kroah-Hartman 	struct kset *kset;
963d9cd8f37SDave Young 	int retval;
964b727c702SGreg Kroah-Hartman 
965b727c702SGreg Kroah-Hartman 	kset = kzalloc(sizeof(*kset), GFP_KERNEL);
966b727c702SGreg Kroah-Hartman 	if (!kset)
967b727c702SGreg Kroah-Hartman 		return NULL;
968b7165ebbSKees Cook 	retval = kobject_set_name(&kset->kobj, "%s", name);
969d9cd8f37SDave Young 	if (retval) {
970d9cd8f37SDave Young 		kfree(kset);
971d9cd8f37SDave Young 		return NULL;
972d9cd8f37SDave Young 	}
973b727c702SGreg Kroah-Hartman 	kset->uevent_ops = uevent_ops;
974b727c702SGreg Kroah-Hartman 	kset->kobj.parent = parent_kobj;
975b727c702SGreg Kroah-Hartman 
976b727c702SGreg Kroah-Hartman 	/*
977386f275fSKay Sievers 	 * The kobject of this kset will have a type of kset_ktype and belong to
978b727c702SGreg Kroah-Hartman 	 * no kset itself.  That way we can properly free it when it is
979b727c702SGreg Kroah-Hartman 	 * finished being used.
980b727c702SGreg Kroah-Hartman 	 */
981386f275fSKay Sievers 	kset->kobj.ktype = &kset_ktype;
982b727c702SGreg Kroah-Hartman 	kset->kobj.kset = NULL;
983b727c702SGreg Kroah-Hartman 
984b727c702SGreg Kroah-Hartman 	return kset;
985b727c702SGreg Kroah-Hartman }
986b727c702SGreg Kroah-Hartman 
987b727c702SGreg Kroah-Hartman /**
988ed856349STobin C. Harding  * kset_create_and_add() - Create a struct kset dynamically and add it to sysfs.
989b727c702SGreg Kroah-Hartman  *
990b727c702SGreg Kroah-Hartman  * @name: the name for the kset
991b727c702SGreg Kroah-Hartman  * @uevent_ops: a struct kset_uevent_ops for the kset
992b727c702SGreg Kroah-Hartman  * @parent_kobj: the parent kobject of this kset, if any.
993b727c702SGreg Kroah-Hartman  *
994b727c702SGreg Kroah-Hartman  * This function creates a kset structure dynamically and registers it
995b727c702SGreg Kroah-Hartman  * with sysfs.  When you are finished with this structure, call
996b727c702SGreg Kroah-Hartman  * kset_unregister() and the structure will be dynamically freed when it
997b727c702SGreg Kroah-Hartman  * is no longer being used.
998b727c702SGreg Kroah-Hartman  *
999b727c702SGreg Kroah-Hartman  * If the kset was not able to be created, NULL will be returned.
1000b727c702SGreg Kroah-Hartman  */
kset_create_and_add(const char * name,const struct kset_uevent_ops * uevent_ops,struct kobject * parent_kobj)1001b727c702SGreg Kroah-Hartman struct kset *kset_create_and_add(const char *name,
10029cd43611SEmese Revfy 				 const struct kset_uevent_ops *uevent_ops,
1003b727c702SGreg Kroah-Hartman 				 struct kobject *parent_kobj)
1004b727c702SGreg Kroah-Hartman {
1005b727c702SGreg Kroah-Hartman 	struct kset *kset;
1006b727c702SGreg Kroah-Hartman 	int error;
1007b727c702SGreg Kroah-Hartman 
1008b727c702SGreg Kroah-Hartman 	kset = kset_create(name, uevent_ops, parent_kobj);
1009b727c702SGreg Kroah-Hartman 	if (!kset)
1010b727c702SGreg Kroah-Hartman 		return NULL;
1011b727c702SGreg Kroah-Hartman 	error = kset_register(kset);
1012b727c702SGreg Kroah-Hartman 	if (error) {
1013b727c702SGreg Kroah-Hartman 		kfree(kset);
1014b727c702SGreg Kroah-Hartman 		return NULL;
1015b727c702SGreg Kroah-Hartman 	}
1016b727c702SGreg Kroah-Hartman 	return kset;
1017b727c702SGreg Kroah-Hartman }
1018b727c702SGreg Kroah-Hartman EXPORT_SYMBOL_GPL(kset_create_and_add);
1019b727c702SGreg Kroah-Hartman 
1020bc451f20SEric W. Biederman 
1021bc451f20SEric W. Biederman static DEFINE_SPINLOCK(kobj_ns_type_lock);
1022bc451f20SEric W. Biederman static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
1023bc451f20SEric W. Biederman 
kobj_ns_type_register(const struct kobj_ns_type_operations * ops)1024bc451f20SEric W. Biederman int kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
1025bc451f20SEric W. Biederman {
1026bc451f20SEric W. Biederman 	enum kobj_ns_type type = ops->type;
1027bc451f20SEric W. Biederman 	int error;
1028bc451f20SEric W. Biederman 
1029bc451f20SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1030bc451f20SEric W. Biederman 
1031bc451f20SEric W. Biederman 	error = -EINVAL;
1032e2dfa1d5SZhen Lei 	if (!kobj_ns_type_is_valid(type))
1033bc451f20SEric W. Biederman 		goto out;
1034bc451f20SEric W. Biederman 
1035bc451f20SEric W. Biederman 	error = -EBUSY;
1036bc451f20SEric W. Biederman 	if (kobj_ns_ops_tbl[type])
1037bc451f20SEric W. Biederman 		goto out;
1038bc451f20SEric W. Biederman 
1039bc451f20SEric W. Biederman 	error = 0;
1040bc451f20SEric W. Biederman 	kobj_ns_ops_tbl[type] = ops;
1041bc451f20SEric W. Biederman 
1042bc451f20SEric W. Biederman out:
1043bc451f20SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
1044bc451f20SEric W. Biederman 	return error;
1045bc451f20SEric W. Biederman }
1046bc451f20SEric W. Biederman 
kobj_ns_type_registered(enum kobj_ns_type type)1047bc451f20SEric W. Biederman int kobj_ns_type_registered(enum kobj_ns_type type)
1048bc451f20SEric W. Biederman {
1049bc451f20SEric W. Biederman 	int registered = 0;
1050bc451f20SEric W. Biederman 
1051bc451f20SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1052e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type))
1053bc451f20SEric W. Biederman 		registered = kobj_ns_ops_tbl[type] != NULL;
1054bc451f20SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
1055bc451f20SEric W. Biederman 
1056bc451f20SEric W. Biederman 	return registered;
1057bc451f20SEric W. Biederman }
1058bc451f20SEric W. Biederman 
kobj_child_ns_ops(const struct kobject * parent)1059542aa246SGreg Kroah-Hartman const struct kobj_ns_type_operations *kobj_child_ns_ops(const struct kobject *parent)
1060bc451f20SEric W. Biederman {
1061bc451f20SEric W. Biederman 	const struct kobj_ns_type_operations *ops = NULL;
1062bc451f20SEric W. Biederman 
1063*7f414d30SGreg Kroah-Hartman 	if (parent && parent->ktype && parent->ktype->child_ns_type)
1064bc451f20SEric W. Biederman 		ops = parent->ktype->child_ns_type(parent);
1065bc451f20SEric W. Biederman 
1066bc451f20SEric W. Biederman 	return ops;
1067bc451f20SEric W. Biederman }
1068bc451f20SEric W. Biederman 
kobj_ns_ops(const struct kobject * kobj)1069542aa246SGreg Kroah-Hartman const struct kobj_ns_type_operations *kobj_ns_ops(const struct kobject *kobj)
1070bc451f20SEric W. Biederman {
1071bc451f20SEric W. Biederman 	return kobj_child_ns_ops(kobj->parent);
1072bc451f20SEric W. Biederman }
1073bc451f20SEric W. Biederman 
kobj_ns_current_may_mount(enum kobj_ns_type type)10747dc5dbc8SEric W. Biederman bool kobj_ns_current_may_mount(enum kobj_ns_type type)
10757dc5dbc8SEric W. Biederman {
1076730d7d33SEric W. Biederman 	bool may_mount = true;
10777dc5dbc8SEric W. Biederman 
10787dc5dbc8SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1079e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
10807dc5dbc8SEric W. Biederman 		may_mount = kobj_ns_ops_tbl[type]->current_may_mount();
10817dc5dbc8SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
10827dc5dbc8SEric W. Biederman 
10837dc5dbc8SEric W. Biederman 	return may_mount;
10847dc5dbc8SEric W. Biederman }
1085bc451f20SEric W. Biederman 
kobj_ns_grab_current(enum kobj_ns_type type)1086a685e089SAl Viro void *kobj_ns_grab_current(enum kobj_ns_type type)
1087bc451f20SEric W. Biederman {
1088a685e089SAl Viro 	void *ns = NULL;
1089bc451f20SEric W. Biederman 
1090bc451f20SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1091e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
1092a685e089SAl Viro 		ns = kobj_ns_ops_tbl[type]->grab_current_ns();
1093bc451f20SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
1094bc451f20SEric W. Biederman 
1095bc451f20SEric W. Biederman 	return ns;
1096bc451f20SEric W. Biederman }
1097172856eaSBart Van Assche EXPORT_SYMBOL_GPL(kobj_ns_grab_current);
1098bc451f20SEric W. Biederman 
kobj_ns_netlink(enum kobj_ns_type type,struct sock * sk)1099bc451f20SEric W. Biederman const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk)
1100bc451f20SEric W. Biederman {
1101bc451f20SEric W. Biederman 	const void *ns = NULL;
1102bc451f20SEric W. Biederman 
1103bc451f20SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1104e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
1105bc451f20SEric W. Biederman 		ns = kobj_ns_ops_tbl[type]->netlink_ns(sk);
1106bc451f20SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
1107bc451f20SEric W. Biederman 
1108bc451f20SEric W. Biederman 	return ns;
1109bc451f20SEric W. Biederman }
1110bc451f20SEric W. Biederman 
kobj_ns_initial(enum kobj_ns_type type)1111bc451f20SEric W. Biederman const void *kobj_ns_initial(enum kobj_ns_type type)
1112bc451f20SEric W. Biederman {
1113bc451f20SEric W. Biederman 	const void *ns = NULL;
1114bc451f20SEric W. Biederman 
1115bc451f20SEric W. Biederman 	spin_lock(&kobj_ns_type_lock);
1116e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type) && kobj_ns_ops_tbl[type])
1117bc451f20SEric W. Biederman 		ns = kobj_ns_ops_tbl[type]->initial_ns();
1118bc451f20SEric W. Biederman 	spin_unlock(&kobj_ns_type_lock);
1119bc451f20SEric W. Biederman 
1120bc451f20SEric W. Biederman 	return ns;
1121bc451f20SEric W. Biederman }
1122bc451f20SEric W. Biederman 
kobj_ns_drop(enum kobj_ns_type type,void * ns)1123a685e089SAl Viro void kobj_ns_drop(enum kobj_ns_type type, void *ns)
1124bc451f20SEric W. Biederman {
1125a685e089SAl Viro 	spin_lock(&kobj_ns_type_lock);
1126e2dfa1d5SZhen Lei 	if (kobj_ns_type_is_valid(type) &&
1127a685e089SAl Viro 	    kobj_ns_ops_tbl[type] && kobj_ns_ops_tbl[type]->drop_ns)
1128a685e089SAl Viro 		kobj_ns_ops_tbl[type]->drop_ns(ns);
1129a685e089SAl Viro 	spin_unlock(&kobj_ns_type_lock);
1130bc451f20SEric W. Biederman }
1131172856eaSBart Van Assche EXPORT_SYMBOL_GPL(kobj_ns_drop);
1132