diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kobject.c | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index 669bf190d4fb..151089788c21 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -13,11 +13,33 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <linux/kobject.h> | 15 | #include <linux/kobject.h> |
16 | #include <linux/kobj_completion.h> | ||
16 | #include <linux/string.h> | 17 | #include <linux/string.h> |
17 | #include <linux/export.h> | 18 | #include <linux/export.h> |
18 | #include <linux/stat.h> | 19 | #include <linux/stat.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | 21 | ||
22 | /** | ||
23 | * kobject_namespace - return @kobj's namespace tag | ||
24 | * @kobj: kobject in question | ||
25 | * | ||
26 | * Returns namespace tag of @kobj if its parent has namespace ops enabled | ||
27 | * and thus @kobj should have a namespace tag associated with it. Returns | ||
28 | * %NULL otherwise. | ||
29 | */ | ||
30 | const void *kobject_namespace(struct kobject *kobj) | ||
31 | { | ||
32 | const struct kobj_ns_type_operations *ns_ops = kobj_ns_ops(kobj); | ||
33 | const void *ns; | ||
34 | |||
35 | if (!ns_ops || ns_ops->type == KOBJ_NS_TYPE_NONE) | ||
36 | return NULL; | ||
37 | |||
38 | ns = kobj->ktype->namespace(kobj); | ||
39 | WARN_ON(!ns); /* @kobj in a namespace is required to have !NULL tag */ | ||
40 | return ns; | ||
41 | } | ||
42 | |||
21 | /* | 43 | /* |
22 | * populate_dir - populate directory with attributes. | 44 | * populate_dir - populate directory with attributes. |
23 | * @kobj: object we're working on. | 45 | * @kobj: object we're working on. |
@@ -46,8 +68,9 @@ static int populate_dir(struct kobject *kobj) | |||
46 | 68 | ||
47 | static int create_dir(struct kobject *kobj) | 69 | static int create_dir(struct kobject *kobj) |
48 | { | 70 | { |
49 | int error = 0; | 71 | int error; |
50 | error = sysfs_create_dir(kobj); | 72 | |
73 | error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj)); | ||
51 | if (!error) { | 74 | if (!error) { |
52 | error = populate_dir(kobj); | 75 | error = populate_dir(kobj); |
53 | if (error) | 76 | if (error) |
@@ -428,7 +451,7 @@ int kobject_rename(struct kobject *kobj, const char *new_name) | |||
428 | goto out; | 451 | goto out; |
429 | } | 452 | } |
430 | 453 | ||
431 | error = sysfs_rename_dir(kobj, new_name); | 454 | error = sysfs_rename_dir_ns(kobj, new_name, kobject_namespace(kobj)); |
432 | if (error) | 455 | if (error) |
433 | goto out; | 456 | goto out; |
434 | 457 | ||
@@ -472,6 +495,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) | |||
472 | if (kobj->kset) | 495 | if (kobj->kset) |
473 | new_parent = kobject_get(&kobj->kset->kobj); | 496 | new_parent = kobject_get(&kobj->kset->kobj); |
474 | } | 497 | } |
498 | |||
475 | /* old object path */ | 499 | /* old object path */ |
476 | devpath = kobject_get_path(kobj, GFP_KERNEL); | 500 | devpath = kobject_get_path(kobj, GFP_KERNEL); |
477 | if (!devpath) { | 501 | if (!devpath) { |
@@ -486,7 +510,7 @@ int kobject_move(struct kobject *kobj, struct kobject *new_parent) | |||
486 | sprintf(devpath_string, "DEVPATH_OLD=%s", devpath); | 510 | sprintf(devpath_string, "DEVPATH_OLD=%s", devpath); |
487 | envp[0] = devpath_string; | 511 | envp[0] = devpath_string; |
488 | envp[1] = NULL; | 512 | envp[1] = NULL; |
489 | error = sysfs_move_dir(kobj, new_parent); | 513 | error = sysfs_move_dir_ns(kobj, new_parent, kobject_namespace(kobj)); |
490 | if (error) | 514 | if (error) |
491 | goto out; | 515 | goto out; |
492 | old_parent = kobj->parent; | 516 | old_parent = kobj->parent; |
@@ -727,6 +751,55 @@ const struct sysfs_ops kobj_sysfs_ops = { | |||
727 | }; | 751 | }; |
728 | 752 | ||
729 | /** | 753 | /** |
754 | * kobj_completion_init - initialize a kobj_completion object. | ||
755 | * @kc: kobj_completion | ||
756 | * @ktype: type of kobject to initialize | ||
757 | * | ||
758 | * kobj_completion structures can be embedded within structures with different | ||
759 | * lifetime rules. During the release of the enclosing object, we can | ||
760 | * wait on the release of the kobject so that we don't free it while it's | ||
761 | * still busy. | ||
762 | */ | ||
763 | void kobj_completion_init(struct kobj_completion *kc, struct kobj_type *ktype) | ||
764 | { | ||
765 | init_completion(&kc->kc_unregister); | ||
766 | kobject_init(&kc->kc_kobj, ktype); | ||
767 | } | ||
768 | EXPORT_SYMBOL_GPL(kobj_completion_init); | ||
769 | |||
770 | /** | ||
771 | * kobj_completion_release - release a kobj_completion object | ||
772 | * @kobj: kobject embedded in kobj_completion | ||
773 | * | ||
774 | * Used with kobject_release to notify waiters that the kobject has been | ||
775 | * released. | ||
776 | */ | ||
777 | void kobj_completion_release(struct kobject *kobj) | ||
778 | { | ||
779 | struct kobj_completion *kc = kobj_to_kobj_completion(kobj); | ||
780 | complete(&kc->kc_unregister); | ||
781 | } | ||
782 | EXPORT_SYMBOL_GPL(kobj_completion_release); | ||
783 | |||
784 | /** | ||
785 | * kobj_completion_del_and_wait - release the kobject and wait for it | ||
786 | * @kc: kobj_completion object to release | ||
787 | * | ||
788 | * Delete the kobject from sysfs and drop the reference count. Then wait | ||
789 | * until any other outstanding references are also dropped. This routine | ||
790 | * is only necessary once other references may have been taken on the | ||
791 | * kobject. Typically this happens when the kobject has been published | ||
792 | * to sysfs via kobject_add. | ||
793 | */ | ||
794 | void kobj_completion_del_and_wait(struct kobj_completion *kc) | ||
795 | { | ||
796 | kobject_del(&kc->kc_kobj); | ||
797 | kobject_put(&kc->kc_kobj); | ||
798 | wait_for_completion(&kc->kc_unregister); | ||
799 | } | ||
800 | EXPORT_SYMBOL_GPL(kobj_completion_del_and_wait); | ||
801 | |||
802 | /** | ||
730 | * kset_register - initialize and add a kset. | 803 | * kset_register - initialize and add a kset. |
731 | * @k: kset. | 804 | * @k: kset. |
732 | */ | 805 | */ |