diff options
author | Jeff Mahoney <jeffm@suse.com> | 2013-09-11 13:00:30 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-09-26 19:17:33 -0400 |
commit | eee031649707db3c9920d9498f8d03819b74fc23 (patch) | |
tree | 439bd4f3db8c3f4342a85b93a6cec1c8db4e524c /lib | |
parent | 1296fc02c22cb8bc0cde34fbd1336d1a8d76f1e1 (diff) |
kobject: introduce kobj_completion
A common way to handle kobject lifetimes in embedded in objects with
different lifetime rules is to pair the kobject with a struct completion.
This introduces a kobj_completion structure that can be used in place
of the pairing, along with several convenience functions for
initialization, release, and put-and-wait.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/kobject.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index e769ee3c2fb9..a5a9b13b0648 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -13,6 +13,7 @@ | |||
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> |
@@ -750,6 +751,55 @@ const struct sysfs_ops kobj_sysfs_ops = { | |||
750 | }; | 751 | }; |
751 | 752 | ||
752 | /** | 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 | /** | ||
753 | * kset_register - initialize and add a kset. | 803 | * kset_register - initialize and add a kset. |
754 | * @k: kset. | 804 | * @k: kset. |
755 | */ | 805 | */ |