diff options
Diffstat (limited to 'lib/kobject.c')
-rw-r--r-- | lib/kobject.c | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index 7ce6dc138e90..c2917ffe8bf1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -44,11 +44,11 @@ static int populate_dir(struct kobject * kobj) | |||
44 | return error; | 44 | return error; |
45 | } | 45 | } |
46 | 46 | ||
47 | static int create_dir(struct kobject * kobj) | 47 | static int create_dir(struct kobject * kobj, struct dentry *shadow_parent) |
48 | { | 48 | { |
49 | int error = 0; | 49 | int error = 0; |
50 | if (kobject_name(kobj)) { | 50 | if (kobject_name(kobj)) { |
51 | error = sysfs_create_dir(kobj); | 51 | error = sysfs_create_dir(kobj, shadow_parent); |
52 | if (!error) { | 52 | if (!error) { |
53 | if ((error = populate_dir(kobj))) | 53 | if ((error = populate_dir(kobj))) |
54 | sysfs_remove_dir(kobj); | 54 | sysfs_remove_dir(kobj); |
@@ -126,6 +126,8 @@ EXPORT_SYMBOL_GPL(kobject_get_path); | |||
126 | */ | 126 | */ |
127 | void kobject_init(struct kobject * kobj) | 127 | void kobject_init(struct kobject * kobj) |
128 | { | 128 | { |
129 | if (!kobj) | ||
130 | return; | ||
129 | kref_init(&kobj->kref); | 131 | kref_init(&kobj->kref); |
130 | INIT_LIST_HEAD(&kobj->entry); | 132 | INIT_LIST_HEAD(&kobj->entry); |
131 | init_waitqueue_head(&kobj->poll); | 133 | init_waitqueue_head(&kobj->poll); |
@@ -156,9 +158,10 @@ static void unlink(struct kobject * kobj) | |||
156 | /** | 158 | /** |
157 | * kobject_add - add an object to the hierarchy. | 159 | * kobject_add - add an object to the hierarchy. |
158 | * @kobj: object. | 160 | * @kobj: object. |
161 | * @shadow_parent: sysfs directory to add to. | ||
159 | */ | 162 | */ |
160 | 163 | ||
161 | int kobject_add(struct kobject * kobj) | 164 | int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent) |
162 | { | 165 | { |
163 | int error = 0; | 166 | int error = 0; |
164 | struct kobject * parent; | 167 | struct kobject * parent; |
@@ -189,12 +192,11 @@ int kobject_add(struct kobject * kobj) | |||
189 | } | 192 | } |
190 | kobj->parent = parent; | 193 | kobj->parent = parent; |
191 | 194 | ||
192 | error = create_dir(kobj); | 195 | error = create_dir(kobj, shadow_parent); |
193 | if (error) { | 196 | if (error) { |
194 | /* unlink does the kobject_put() for us */ | 197 | /* unlink does the kobject_put() for us */ |
195 | unlink(kobj); | 198 | unlink(kobj); |
196 | if (parent) | 199 | kobject_put(parent); |
197 | kobject_put(parent); | ||
198 | 200 | ||
199 | /* be noisy on error issues */ | 201 | /* be noisy on error issues */ |
200 | if (error == -EEXIST) | 202 | if (error == -EEXIST) |
@@ -211,6 +213,15 @@ int kobject_add(struct kobject * kobj) | |||
211 | return error; | 213 | return error; |
212 | } | 214 | } |
213 | 215 | ||
216 | /** | ||
217 | * kobject_add - add an object to the hierarchy. | ||
218 | * @kobj: object. | ||
219 | */ | ||
220 | int kobject_add(struct kobject * kobj) | ||
221 | { | ||
222 | return kobject_shadow_add(kobj, NULL); | ||
223 | } | ||
224 | |||
214 | 225 | ||
215 | /** | 226 | /** |
216 | * kobject_register - initialize and add an object. | 227 | * kobject_register - initialize and add an object. |
@@ -303,7 +314,29 @@ int kobject_rename(struct kobject * kobj, const char *new_name) | |||
303 | kobj = kobject_get(kobj); | 314 | kobj = kobject_get(kobj); |
304 | if (!kobj) | 315 | if (!kobj) |
305 | return -EINVAL; | 316 | return -EINVAL; |
306 | error = sysfs_rename_dir(kobj, new_name); | 317 | if (!kobj->parent) |
318 | return -EINVAL; | ||
319 | error = sysfs_rename_dir(kobj, kobj->parent->dentry, new_name); | ||
320 | kobject_put(kobj); | ||
321 | |||
322 | return error; | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * kobject_rename - change the name of an object | ||
327 | * @kobj: object in question. | ||
328 | * @new_name: object's new name | ||
329 | */ | ||
330 | |||
331 | int kobject_shadow_rename(struct kobject * kobj, struct dentry *new_parent, | ||
332 | const char *new_name) | ||
333 | { | ||
334 | int error = 0; | ||
335 | |||
336 | kobj = kobject_get(kobj); | ||
337 | if (!kobj) | ||
338 | return -EINVAL; | ||
339 | error = sysfs_rename_dir(kobj, new_parent, new_name); | ||
307 | kobject_put(kobj); | 340 | kobject_put(kobj); |
308 | 341 | ||
309 | return error; | 342 | return error; |
@@ -312,7 +345,7 @@ int kobject_rename(struct kobject * kobj, const char *new_name) | |||
312 | /** | 345 | /** |
313 | * kobject_move - move object to another parent | 346 | * kobject_move - move object to another parent |
314 | * @kobj: object in question. | 347 | * @kobj: object in question. |
315 | * @new_parent: object's new parent | 348 | * @new_parent: object's new parent (can be NULL) |
316 | */ | 349 | */ |
317 | 350 | ||
318 | int kobject_move(struct kobject *kobj, struct kobject *new_parent) | 351 | int kobject_move(struct kobject *kobj, struct kobject *new_parent) |
@@ -328,8 +361,8 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) | |||
328 | return -EINVAL; | 361 | return -EINVAL; |
329 | new_parent = kobject_get(new_parent); | 362 | new_parent = kobject_get(new_parent); |
330 | if (!new_parent) { | 363 | if (!new_parent) { |
331 | error = -EINVAL; | 364 | if (kobj->kset) |
332 | goto out; | 365 | new_parent = kobject_get(&kobj->kset->kobj); |
333 | } | 366 | } |
334 | /* old object path */ | 367 | /* old object path */ |
335 | devpath = kobject_get_path(kobj, GFP_KERNEL); | 368 | devpath = kobject_get_path(kobj, GFP_KERNEL); |
@@ -366,6 +399,8 @@ out: | |||
366 | 399 | ||
367 | void kobject_del(struct kobject * kobj) | 400 | void kobject_del(struct kobject * kobj) |
368 | { | 401 | { |
402 | if (!kobj) | ||
403 | return; | ||
369 | sysfs_remove_dir(kobj); | 404 | sysfs_remove_dir(kobj); |
370 | unlink(kobj); | 405 | unlink(kobj); |
371 | } | 406 | } |
@@ -377,6 +412,8 @@ void kobject_del(struct kobject * kobj) | |||
377 | 412 | ||
378 | void kobject_unregister(struct kobject * kobj) | 413 | void kobject_unregister(struct kobject * kobj) |
379 | { | 414 | { |
415 | if (!kobj) | ||
416 | return; | ||
380 | pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); | 417 | pr_debug("kobject %s: unregistering\n",kobject_name(kobj)); |
381 | kobject_uevent(kobj, KOBJ_REMOVE); | 418 | kobject_uevent(kobj, KOBJ_REMOVE); |
382 | kobject_del(kobj); | 419 | kobject_del(kobj); |
@@ -414,8 +451,7 @@ void kobject_cleanup(struct kobject * kobj) | |||
414 | t->release(kobj); | 451 | t->release(kobj); |
415 | if (s) | 452 | if (s) |
416 | kset_put(s); | 453 | kset_put(s); |
417 | if (parent) | 454 | kobject_put(parent); |
418 | kobject_put(parent); | ||
419 | } | 455 | } |
420 | 456 | ||
421 | static void kobject_release(struct kref *kref) | 457 | static void kobject_release(struct kref *kref) |
@@ -523,6 +559,8 @@ int kset_add(struct kset * k) | |||
523 | 559 | ||
524 | int kset_register(struct kset * k) | 560 | int kset_register(struct kset * k) |
525 | { | 561 | { |
562 | if (!k) | ||
563 | return -EINVAL; | ||
526 | kset_init(k); | 564 | kset_init(k); |
527 | return kset_add(k); | 565 | return kset_add(k); |
528 | } | 566 | } |
@@ -535,6 +573,8 @@ int kset_register(struct kset * k) | |||
535 | 573 | ||
536 | void kset_unregister(struct kset * k) | 574 | void kset_unregister(struct kset * k) |
537 | { | 575 | { |
576 | if (!k) | ||
577 | return; | ||
538 | kobject_unregister(&k->kobj); | 578 | kobject_unregister(&k->kobj); |
539 | } | 579 | } |
540 | 580 | ||
@@ -586,6 +626,9 @@ int subsystem_register(struct subsystem * s) | |||
586 | { | 626 | { |
587 | int error; | 627 | int error; |
588 | 628 | ||
629 | if (!s) | ||
630 | return -EINVAL; | ||
631 | |||
589 | subsystem_init(s); | 632 | subsystem_init(s); |
590 | pr_debug("subsystem %s: registering\n",s->kset.kobj.name); | 633 | pr_debug("subsystem %s: registering\n",s->kset.kobj.name); |
591 | 634 | ||
@@ -598,6 +641,8 @@ int subsystem_register(struct subsystem * s) | |||
598 | 641 | ||
599 | void subsystem_unregister(struct subsystem * s) | 642 | void subsystem_unregister(struct subsystem * s) |
600 | { | 643 | { |
644 | if (!s) | ||
645 | return; | ||
601 | pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name); | 646 | pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name); |
602 | kset_unregister(&s->kset); | 647 | kset_unregister(&s->kset); |
603 | } | 648 | } |
@@ -612,6 +657,10 @@ void subsystem_unregister(struct subsystem * s) | |||
612 | int subsys_create_file(struct subsystem * s, struct subsys_attribute * a) | 657 | int subsys_create_file(struct subsystem * s, struct subsys_attribute * a) |
613 | { | 658 | { |
614 | int error = 0; | 659 | int error = 0; |
660 | |||
661 | if (!s || !a) | ||
662 | return -EINVAL; | ||
663 | |||
615 | if (subsys_get(s)) { | 664 | if (subsys_get(s)) { |
616 | error = sysfs_create_file(&s->kset.kobj,&a->attr); | 665 | error = sysfs_create_file(&s->kset.kobj,&a->attr); |
617 | subsys_put(s); | 666 | subsys_put(s); |