Blame view

lib/kobject.c 13.7 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
  /*
   * kobject.c - library routines for handling generic kernel objects
   *
   * Copyright (c) 2002-2003 Patrick Mochel <mochel@osdl.org>
f0e7e1bd7   Greg Kroah-Hartman   kobject: update t...
5
6
   * Copyright (c) 2006-2007 Greg Kroah-Hartman <greg@kroah.com>
   * Copyright (c) 2006-2007 Novell Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
9
10
11
12
13
14
15
16
17
18
   *
   * This file is released under the GPLv2.
   *
   *
   * Please see the file Documentation/kobject.txt for critical information
   * about using the kobject interface.
   */
  
  #include <linux/kobject.h>
  #include <linux/string.h>
  #include <linux/module.h>
  #include <linux/stat.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
19
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  
  /**
   *	populate_dir - populate directory with attributes.
   *	@kobj:	object we're working on.
   *
   *	Most subsystems have a set of default attributes that 
   *	are associated with an object that registers with them.
   *	This is a helper called during object registration that 
   *	loops through the default attributes of the subsystem 
   *	and creates attributes files for them in sysfs.
   *
   */
  
  static int populate_dir(struct kobject * kobj)
  {
  	struct kobj_type * t = get_ktype(kobj);
  	struct attribute * attr;
  	int error = 0;
  	int i;
  	
  	if (t && t->default_attrs) {
  		for (i = 0; (attr = t->default_attrs[i]) != NULL; i++) {
  			if ((error = sysfs_create_file(kobj,attr)))
  				break;
  		}
  	}
  	return error;
  }
90bc61359   Eric W. Biederman   sysfs: Remove fir...
48
  static int create_dir(struct kobject * kobj)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
  {
  	int error = 0;
  	if (kobject_name(kobj)) {
90bc61359   Eric W. Biederman   sysfs: Remove fir...
52
  		error = sysfs_create_dir(kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  		if (!error) {
  			if ((error = populate_dir(kobj)))
  				sysfs_remove_dir(kobj);
  		}
  	}
  	return error;
  }
  
  static inline struct kobject * to_kobj(struct list_head * entry)
  {
  	return container_of(entry,struct kobject,entry);
  }
  
  static int get_kobj_path_length(struct kobject *kobj)
  {
  	int length = 1;
  	struct kobject * parent = kobj;
  
  	/* walk up the ancestors until we hit the one pointing to the 
  	 * root.
  	 * Add 1 to strlen for leading '/' of each level.
  	 */
  	do {
b365b3daf   Chuck Ebbert   [PATCH] kobject: ...
76
77
  		if (kobject_name(parent) == NULL)
  			return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  		length += strlen(kobject_name(parent)) + 1;
  		parent = parent->parent;
  	} while (parent);
  	return length;
  }
  
  static void fill_kobj_path(struct kobject *kobj, char *path, int length)
  {
  	struct kobject * parent;
  
  	--length;
  	for (parent = kobj; parent; parent = parent->parent) {
  		int cur = strlen(kobject_name(parent));
  		/* back up enough to print this name with '/' */
  		length -= cur;
  		strncpy (path + length, kobject_name(parent), cur);
  		*(path + --length) = '/';
  	}
  
  	pr_debug("%s: path = '%s'
  ",__FUNCTION__,path);
  }
  
  /**
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
102
   * kobject_get_path - generate and return the path associated with a given kobj and kset pair.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
103
104
105
   *
   * @kobj:	kobject in question, with which to build the path
   * @gfp_mask:	the allocation type used to allocate the path
72fd4a35a   Robert P. J. Day   [PATCH] Numerous ...
106
107
   *
   * The result must be freed by the caller with kfree().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
108
   */
fd4f2df24   Al Viro   [PATCH] gfp_t: lib/*
109
  char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
  {
  	char *path;
  	int len;
  
  	len = get_kobj_path_length(kobj);
b365b3daf   Chuck Ebbert   [PATCH] kobject: ...
115
116
  	if (len == 0)
  		return NULL;
4668edc33   Burman Yan   [PATCH] kernel co...
117
  	path = kzalloc(len, gfp_mask);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
  	if (!path)
  		return NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
  	fill_kobj_path(kobj, path, len);
  
  	return path;
  }
80fc9f532   Dmitry Torokhov   Input: add missin...
124
  EXPORT_SYMBOL_GPL(kobject_get_path);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
126
127
128
129
130
131
  
  /**
   *	kobject_init - initialize object.
   *	@kobj:	object in question.
   */
  void kobject_init(struct kobject * kobj)
  {
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
132
133
  	if (!kobj)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  	kref_init(&kobj->kref);
  	INIT_LIST_HEAD(&kobj->entry);
  	kobj->kset = kset_get(kobj->kset);
  }
  
  
  /**
   *	unlink - remove kobject from kset list.
   *	@kobj:	kobject.
   *
   *	Remove the kobject from the kset list and decrement
   *	its parent's refcount.
   *	This is separated out, so we can use it in both 
   *	kobject_del() and kobject_add() on error.
   */
  
  static void unlink(struct kobject * kobj)
  {
  	if (kobj->kset) {
  		spin_lock(&kobj->kset->list_lock);
  		list_del_init(&kobj->entry);
  		spin_unlock(&kobj->kset->list_lock);
  	}
  	kobject_put(kobj);
  }
  
  /**
90bc61359   Eric W. Biederman   sysfs: Remove fir...
161
   *	kobject_add - add an object to the hierarchy.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
   *	@kobj:	object.
   */
90bc61359   Eric W. Biederman   sysfs: Remove fir...
164
  int kobject_add(struct kobject * kobj)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
166
167
168
169
170
171
  {
  	int error = 0;
  	struct kobject * parent;
  
  	if (!(kobj = kobject_get(kobj)))
  		return -ENOENT;
  	if (!kobj->k_name)
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
172
  		kobject_set_name(kobj, "NO_NAME");
135077011   Martin Stoilov   kobject: kobj->k_...
173
  	if (!*kobj->k_name) {
c171fef5c   Greg Kroah-Hartman   [PATCH] kobject_a...
174
175
176
  		pr_debug("kobject attempted to be registered with no name!
  ");
  		WARN_ON(1);
88db4721d   Cornelia Huck   kobject: kobject_...
177
  		kobject_put(kobj);
c171fef5c   Greg Kroah-Hartman   [PATCH] kobject_a...
178
179
  		return -EINVAL;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
183
184
  	parent = kobject_get(kobj->parent);
  
  	pr_debug("kobject %s: registering. parent: %s, set: %s
  ",
  		 kobject_name(kobj), parent ? kobject_name(parent) : "<NULL>", 
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
185
  		 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>" );
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
  
  	if (kobj->kset) {
  		spin_lock(&kobj->kset->list_lock);
  
  		if (!parent)
  			parent = kobject_get(&kobj->kset->kobj);
  
  		list_add_tail(&kobj->entry,&kobj->kset->list);
  		spin_unlock(&kobj->kset->list_lock);
460f7e9a1   Dmitriy Monakhov   kobject: kobject_...
195
  		kobj->parent = parent;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
196
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197

90bc61359   Eric W. Biederman   sysfs: Remove fir...
198
  	error = create_dir(kobj);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
  	if (error) {
  		/* unlink does the kobject_put() for us */
  		unlink(kobj);
b067db49e   Mariusz Kozlowski   kobject: kobject_...
202
  		kobject_put(parent);
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
203
204
205
  
  		/* be noisy on error issues */
  		if (error == -EEXIST)
5c73a3fba   Greg Kroah-Hartman   kobject: use the ...
206
207
208
209
  			printk(KERN_ERR "kobject_add failed for %s with "
  			       "-EEXIST, don't try to register things with "
  			       "the same name in the same directory.
  ",
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
210
211
  			       kobject_name(kobj));
  		else
5c73a3fba   Greg Kroah-Hartman   kobject: use the ...
212
213
  			printk(KERN_ERR "kobject_add failed for %s (%d)
  ",
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
214
  			       kobject_name(kobj), error);
5c73a3fba   Greg Kroah-Hartman   kobject: use the ...
215
  		dump_stack();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
217
218
219
  	}
  
  	return error;
  }
b592fcfe7   Eric W. Biederman   sysfs: Shadow dir...
220
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
225
226
   *	kobject_register - initialize and add an object.
   *	@kobj:	object in question.
   */
  
  int kobject_register(struct kobject * kobj)
  {
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
227
  	int error = -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
229
230
  	if (kobj) {
  		kobject_init(kobj);
  		error = kobject_add(kobj);
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
231
  		if (!error)
312c004d3   Kay Sievers   [PATCH] driver co...
232
  			kobject_uevent(kobj, KOBJ_ADD);
dcd0da002   Greg Kroah-Hartman   [PATCH] Kobject: ...
233
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
234
235
236
237
238
239
240
  	return error;
  }
  
  
  /**
   *	kobject_set_name - Set the name of an object
   *	@kobj:	object.
67be2dd1b   Martin Waitz   [PATCH] DocBook: ...
241
   *	@fmt:	format string used to build the name
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
245
246
   *
   *	If strlen(name) >= KOBJ_NAME_LEN, then use a dynamically allocated
   *	string that @kobj->k_name points to. Otherwise, use the static 
   *	@kobj->name array.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
  int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
  {
  	int error = 0;
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
250
  	int limit;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
  	int need;
  	va_list args;
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
253
  	char *name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
255
256
257
258
259
260
261
262
  	/* find out how big a buffer we need */
  	name = kmalloc(1024, GFP_KERNEL);
  	if (!name) {
  		error = -ENOMEM;
  		goto done;
  	}
  	va_start(args, fmt);
  	need = vsnprintf(name, 1024, fmt, args);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
  	va_end(args);
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
  	kfree(name);
  
  	/* Allocate the new space and copy the string in */
  	limit = need + 1;
  	name = kmalloc(limit, GFP_KERNEL);
  	if (!name) {
  		error = -ENOMEM;
  		goto done;
  	}
  	va_start(args, fmt);
  	need = vsnprintf(name, limit, fmt, args);
  	va_end(args);
  
  	/* something wrong with the string we copied? */
  	if (need >= limit) {
  		kfree(name);
  		error = -EFAULT;
  		goto done;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
283
284
  	}
  
  	/* Free the old name, if necessary. */
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
285
  	kfree(kobj->k_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
287
288
  
  	/* Now, set the new name */
  	kobj->k_name = name;
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
289
  done:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  EXPORT_SYMBOL(kobject_set_name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
294
295
296
297
  /**
   *	kobject_rename - change the name of an object
   *	@kobj:	object in question.
   *	@new_name: object's new name
   */
f3b4f3c6d   Dmitry Torokhov   [PATCH] Make kobj...
298
  int kobject_rename(struct kobject * kobj, const char *new_name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
300
  {
  	int error = 0;
ca2f37dbc   Jean Tourrilhes   Driver core: noti...
301
302
303
  	const char *devpath = NULL;
  	char *devpath_string = NULL;
  	char *envp[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304
305
306
307
  
  	kobj = kobject_get(kobj);
  	if (!kobj)
  		return -EINVAL;
b592fcfe7   Eric W. Biederman   sysfs: Shadow dir...
308
309
  	if (!kobj->parent)
  		return -EINVAL;
ca2f37dbc   Jean Tourrilhes   Driver core: noti...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
  
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
  	if (!devpath) {
  		error = -ENOMEM;
  		goto out;
  	}
  	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
  	if (!devpath_string) {
  		error = -ENOMEM;
  		goto out;
  	}
  	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
  	envp[0] = devpath_string;
  	envp[1] = NULL;
  	/* Note : if we want to send the new name alone, not the full path,
  	 * we could probably use kobject_name(kobj); */
90bc61359   Eric W. Biederman   sysfs: Remove fir...
326
  	error = sysfs_rename_dir(kobj, new_name);
ca2f37dbc   Jean Tourrilhes   Driver core: noti...
327
328
329
330
331
332
333
334
335
336
  
  	/* This function is mostly/only used for network interface.
  	 * Some hotplug package track interfaces by their name and
  	 * therefore want to know when the name is changed by the user. */
  	if (!error)
  		kobject_uevent_env(kobj, KOBJ_MOVE, envp);
  
  out:
  	kfree(devpath_string);
  	kfree(devpath);
b592fcfe7   Eric W. Biederman   sysfs: Shadow dir...
337
338
339
340
341
342
  	kobject_put(kobj);
  
  	return error;
  }
  
  /**
8a82472f8   Cornelia Huck   driver core: Intr...
343
344
   *	kobject_move - move object to another parent
   *	@kobj:	object in question.
c744aeae9   Cornelia Huck   driver core: Allo...
345
   *	@new_parent: object's new parent (can be NULL)
8a82472f8   Cornelia Huck   driver core: Intr...
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
   */
  
  int kobject_move(struct kobject *kobj, struct kobject *new_parent)
  {
  	int error;
  	struct kobject *old_parent;
  	const char *devpath = NULL;
  	char *devpath_string = NULL;
  	char *envp[2];
  
  	kobj = kobject_get(kobj);
  	if (!kobj)
  		return -EINVAL;
  	new_parent = kobject_get(new_parent);
  	if (!new_parent) {
c744aeae9   Cornelia Huck   driver core: Allo...
361
362
  		if (kobj->kset)
  			new_parent = kobject_get(&kobj->kset->kobj);
8a82472f8   Cornelia Huck   driver core: Intr...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
  	}
  	/* old object path */
  	devpath = kobject_get_path(kobj, GFP_KERNEL);
  	if (!devpath) {
  		error = -ENOMEM;
  		goto out;
  	}
  	devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL);
  	if (!devpath_string) {
  		error = -ENOMEM;
  		goto out;
  	}
  	sprintf(devpath_string, "DEVPATH_OLD=%s", devpath);
  	envp[0] = devpath_string;
  	envp[1] = NULL;
  	error = sysfs_move_dir(kobj, new_parent);
  	if (error)
  		goto out;
  	old_parent = kobj->parent;
  	kobj->parent = new_parent;
9e993efb0   Dmitriy Monakhov   kobject: new_devi...
383
  	new_parent = NULL;
8a82472f8   Cornelia Huck   driver core: Intr...
384
385
386
  	kobject_put(old_parent);
  	kobject_uevent_env(kobj, KOBJ_MOVE, envp);
  out:
9e993efb0   Dmitriy Monakhov   kobject: new_devi...
387
  	kobject_put(new_parent);
8a82472f8   Cornelia Huck   driver core: Intr...
388
389
390
391
392
393
394
  	kobject_put(kobj);
  	kfree(devpath_string);
  	kfree(devpath);
  	return error;
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
396
397
398
399
400
   *	kobject_del - unlink kobject from hierarchy.
   * 	@kobj:	object.
   */
  
  void kobject_del(struct kobject * kobj)
  {
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
401
402
  	if (!kobj)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
404
405
406
407
408
409
410
411
412
413
  	sysfs_remove_dir(kobj);
  	unlink(kobj);
  }
  
  /**
   *	kobject_unregister - remove object from hierarchy and decrement refcount.
   *	@kobj:	object going away.
   */
  
  void kobject_unregister(struct kobject * kobj)
  {
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
414
415
  	if (!kobj)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
416
417
  	pr_debug("kobject %s: unregistering
  ",kobject_name(kobj));
312c004d3   Kay Sievers   [PATCH] driver co...
418
  	kobject_uevent(kobj, KOBJ_REMOVE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  	kobject_del(kobj);
  	kobject_put(kobj);
  }
  
  /**
   *	kobject_get - increment refcount for object.
   *	@kobj:	object.
   */
  
  struct kobject * kobject_get(struct kobject * kobj)
  {
  	if (kobj)
  		kref_get(&kobj->kref);
  	return kobj;
  }
  
  /**
   *	kobject_cleanup - free kobject resources. 
   *	@kobj:	object.
   */
  
  void kobject_cleanup(struct kobject * kobj)
  {
  	struct kobj_type * t = get_ktype(kobj);
  	struct kset * s = kobj->kset;
  	struct kobject * parent = kobj->parent;
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
445
  	const char *name = kobj->k_name;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
447
448
  
  	pr_debug("kobject %s: cleaning up
  ",kobject_name(kobj));
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
449
  	if (t && t->release) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
450
  		t->release(kobj);
ce2c9cb02   Greg Kroah-Hartman   kobject: remove t...
451
452
453
454
455
  		/* If we have a release function, we can guess that this was
  		 * not a statically allocated kobject, so we should be safe to
  		 * free the name */
  		kfree(name);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
457
  	if (s)
  		kset_put(s);
b067db49e   Mariusz Kozlowski   kobject: kobject_...
458
  	kobject_put(parent);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
  }
  
  static void kobject_release(struct kref *kref)
  {
  	kobject_cleanup(container_of(kref, struct kobject, kref));
  }
  
  /**
   *	kobject_put - decrement refcount for object.
   *	@kobj:	object.
   *
   *	Decrement the refcount, and if 0, call kobject_cleanup().
   */
  void kobject_put(struct kobject * kobj)
  {
  	if (kobj)
  		kref_put(&kobj->kref, kobject_release);
  }
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
477
478
479
480
481
482
483
484
485
486
487
488
  static void dir_release(struct kobject *kobj)
  {
  	kfree(kobj);
  }
  
  static struct kobj_type dir_ktype = {
  	.release	= dir_release,
  	.sysfs_ops	= NULL,
  	.default_attrs	= NULL,
  };
  
  /**
2753133eb   Eric W. Biederman   kobject: Comment ...
489
   *	kobject_kset_add_dir - add sub directory of object.
864062457   Kay Sievers   driver core: fix ...
490
   *	@kset:		kset the directory is belongs to.
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
491
492
493
494
495
   *	@parent:	object in which a directory is created.
   *	@name:	directory name.
   *
   *	Add a plain directory object as child of given object.
   */
864062457   Kay Sievers   driver core: fix ...
496
497
  struct kobject *kobject_kset_add_dir(struct kset *kset,
  				     struct kobject *parent, const char *name)
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
498
499
  {
  	struct kobject *k;
10188012d   Randy Dunlap   kobject: must_che...
500
  	int ret;
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
501
502
503
504
505
506
507
  
  	if (!parent)
  		return NULL;
  
  	k = kzalloc(sizeof(*k), GFP_KERNEL);
  	if (!k)
  		return NULL;
864062457   Kay Sievers   driver core: fix ...
508
  	k->kset = kset;
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
509
510
511
  	k->parent = parent;
  	k->ktype = &dir_ktype;
  	kobject_set_name(k, name);
10188012d   Randy Dunlap   kobject: must_che...
512
513
  	ret = kobject_register(k);
  	if (ret < 0) {
2753133eb   Eric W. Biederman   kobject: Comment ...
514
515
516
  		printk(KERN_WARNING "%s: kobject_register error: %d
  ",
  			__func__, ret);
10188012d   Randy Dunlap   kobject: must_che...
517
518
519
  		kobject_del(k);
  		return NULL;
  	}
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
520
521
522
  
  	return k;
  }
7423172a5   Jun'ichi Nomura   [PATCH] kobject_a...
523

2753133eb   Eric W. Biederman   kobject: Comment ...
524
525
526
527
528
529
530
  /**
   *	kobject_add_dir - add sub directory of object.
   *	@parent:	object in which a directory is created.
   *	@name:	directory name.
   *
   *	Add a plain directory object as child of given object.
   */
864062457   Kay Sievers   driver core: fix ...
531
532
533
534
  struct kobject *kobject_add_dir(struct kobject *parent, const char *name)
  {
  	return kobject_kset_add_dir(NULL, parent, name);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
  /**
   *	kset_init - initialize a kset for use
   *	@k:	kset 
   */
  
  void kset_init(struct kset * k)
  {
  	kobject_init(&k->kobj);
  	INIT_LIST_HEAD(&k->list);
  	spin_lock_init(&k->list_lock);
  }
  
  
  /**
   *	kset_add - add a kset object to the hierarchy.
   *	@k:	kset.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
551
552
553
554
   */
  
  int kset_add(struct kset * k)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
555
556
557
558
559
560
561
562
563
564
565
  	return kobject_add(&k->kobj);
  }
  
  
  /**
   *	kset_register - initialize and add a kset.
   *	@k:	kset.
   */
  
  int kset_register(struct kset * k)
  {
80f03e349   Kay Sievers   Driver core: add ...
566
  	int err;
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
567
568
  	if (!k)
  		return -EINVAL;
80f03e349   Kay Sievers   Driver core: add ...
569

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570
  	kset_init(k);
80f03e349   Kay Sievers   Driver core: add ...
571
572
573
574
575
  	err = kset_add(k);
  	if (err)
  		return err;
  	kobject_uevent(&k->kobj, KOBJ_ADD);
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
577
578
579
580
581
582
583
584
585
  }
  
  
  /**
   *	kset_unregister - remove a kset.
   *	@k:	kset.
   */
  
  void kset_unregister(struct kset * k)
  {
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
586
587
  	if (!k)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
  	kobject_unregister(&k->kobj);
  }
  
  
  /**
   *	kset_find_obj - search for object in kset.
   *	@kset:	kset we're looking in.
   *	@name:	object's name.
   *
   *	Lock kset via @kset->subsys, and iterate over @kset->list,
   *	looking for a matching kobject. If matching object is found
   *	take a reference and return the object.
   */
  
  struct kobject * kset_find_obj(struct kset * kset, const char * name)
  {
  	struct list_head * entry;
  	struct kobject * ret = NULL;
  
  	spin_lock(&kset->list_lock);
  	list_for_each(entry,&kset->list) {
  		struct kobject * k = to_kobj(entry);
  		if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
  			ret = kobject_get(k);
  			break;
  		}
  	}
  	spin_unlock(&kset->list_lock);
  	return ret;
  }
823bccfc4   Greg Kroah-Hartman   remove "struct su...
618
  int subsystem_register(struct kset *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  {
823bccfc4   Greg Kroah-Hartman   remove "struct su...
620
  	return kset_register(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
621
  }
823bccfc4   Greg Kroah-Hartman   remove "struct su...
622
  void subsystem_unregister(struct kset *s)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  {
823bccfc4   Greg Kroah-Hartman   remove "struct su...
624
  	kset_unregister(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
625
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626
627
628
629
630
  /**
   *	subsystem_create_file - export sysfs attribute file.
   *	@s:	subsystem.
   *	@a:	subsystem attribute descriptor.
   */
823bccfc4   Greg Kroah-Hartman   remove "struct su...
631
  int subsys_create_file(struct kset *s, struct subsys_attribute *a)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
  {
  	int error = 0;
31b9025aa   Greg Kroah-Hartman   Kobject: make kob...
634
635
636
  
  	if (!s || !a)
  		return -EINVAL;
1ef4cfac0   Greg Kroah-Hartman   Driver core: remo...
637
  	if (kset_get(s)) {
823bccfc4   Greg Kroah-Hartman   remove "struct su...
638
  		error = sysfs_create_file(&s->kobj, &a->attr);
6e9d930d1   Greg Kroah-Hartman   Driver core: remo...
639
  		kset_put(s);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
640
641
642
  	}
  	return error;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
643
644
645
646
647
648
649
650
651
652
  EXPORT_SYMBOL(kobject_init);
  EXPORT_SYMBOL(kobject_register);
  EXPORT_SYMBOL(kobject_unregister);
  EXPORT_SYMBOL(kobject_get);
  EXPORT_SYMBOL(kobject_put);
  EXPORT_SYMBOL(kobject_add);
  EXPORT_SYMBOL(kobject_del);
  
  EXPORT_SYMBOL(kset_register);
  EXPORT_SYMBOL(kset_unregister);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
654
655
656
  EXPORT_SYMBOL(subsystem_register);
  EXPORT_SYMBOL(subsystem_unregister);
  EXPORT_SYMBOL(subsys_create_file);