diff options
Diffstat (limited to 'lib/kobject.c')
-rw-r--r-- | lib/kobject.c | 160 |
1 files changed, 157 insertions, 3 deletions
diff --git a/lib/kobject.c b/lib/kobject.c index b512b746d2af..82dc34c095c2 100644 --- a/lib/kobject.c +++ b/lib/kobject.c | |||
@@ -700,7 +700,7 @@ static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr, | |||
700 | return ret; | 700 | return ret; |
701 | } | 701 | } |
702 | 702 | ||
703 | struct sysfs_ops kobj_sysfs_ops = { | 703 | const struct sysfs_ops kobj_sysfs_ops = { |
704 | .show = kobj_attr_show, | 704 | .show = kobj_attr_show, |
705 | .store = kobj_attr_store, | 705 | .store = kobj_attr_store, |
706 | }; | 706 | }; |
@@ -746,17 +746,56 @@ void kset_unregister(struct kset *k) | |||
746 | */ | 746 | */ |
747 | struct kobject *kset_find_obj(struct kset *kset, const char *name) | 747 | struct kobject *kset_find_obj(struct kset *kset, const char *name) |
748 | { | 748 | { |
749 | return kset_find_obj_hinted(kset, name, NULL); | ||
750 | } | ||
751 | |||
752 | /** | ||
753 | * kset_find_obj_hinted - search for object in kset given a predecessor hint. | ||
754 | * @kset: kset we're looking in. | ||
755 | * @name: object's name. | ||
756 | * @hint: hint to possible object's predecessor. | ||
757 | * | ||
758 | * Check the hint's next object and if it is a match return it directly, | ||
759 | * otherwise, fall back to the behavior of kset_find_obj(). Either way | ||
760 | * a reference for the returned object is held and the reference on the | ||
761 | * hinted object is released. | ||
762 | */ | ||
763 | struct kobject *kset_find_obj_hinted(struct kset *kset, const char *name, | ||
764 | struct kobject *hint) | ||
765 | { | ||
749 | struct kobject *k; | 766 | struct kobject *k; |
750 | struct kobject *ret = NULL; | 767 | struct kobject *ret = NULL; |
751 | 768 | ||
752 | spin_lock(&kset->list_lock); | 769 | spin_lock(&kset->list_lock); |
770 | |||
771 | if (!hint) | ||
772 | goto slow_search; | ||
773 | |||
774 | /* end of list detection */ | ||
775 | if (hint->entry.next == kset->list.next) | ||
776 | goto slow_search; | ||
777 | |||
778 | k = container_of(hint->entry.next, struct kobject, entry); | ||
779 | if (!kobject_name(k) || strcmp(kobject_name(k), name)) | ||
780 | goto slow_search; | ||
781 | |||
782 | ret = kobject_get(k); | ||
783 | goto unlock_exit; | ||
784 | |||
785 | slow_search: | ||
753 | list_for_each_entry(k, &kset->list, entry) { | 786 | list_for_each_entry(k, &kset->list, entry) { |
754 | if (kobject_name(k) && !strcmp(kobject_name(k), name)) { | 787 | if (kobject_name(k) && !strcmp(kobject_name(k), name)) { |
755 | ret = kobject_get(k); | 788 | ret = kobject_get(k); |
756 | break; | 789 | break; |
757 | } | 790 | } |
758 | } | 791 | } |
792 | |||
793 | unlock_exit: | ||
759 | spin_unlock(&kset->list_lock); | 794 | spin_unlock(&kset->list_lock); |
795 | |||
796 | if (hint) | ||
797 | kobject_put(hint); | ||
798 | |||
760 | return ret; | 799 | return ret; |
761 | } | 800 | } |
762 | 801 | ||
@@ -789,7 +828,7 @@ static struct kobj_type kset_ktype = { | |||
789 | * If the kset was not able to be created, NULL will be returned. | 828 | * If the kset was not able to be created, NULL will be returned. |
790 | */ | 829 | */ |
791 | static struct kset *kset_create(const char *name, | 830 | static struct kset *kset_create(const char *name, |
792 | struct kset_uevent_ops *uevent_ops, | 831 | const struct kset_uevent_ops *uevent_ops, |
793 | struct kobject *parent_kobj) | 832 | struct kobject *parent_kobj) |
794 | { | 833 | { |
795 | struct kset *kset; | 834 | struct kset *kset; |
@@ -832,7 +871,7 @@ static struct kset *kset_create(const char *name, | |||
832 | * If the kset was not able to be created, NULL will be returned. | 871 | * If the kset was not able to be created, NULL will be returned. |
833 | */ | 872 | */ |
834 | struct kset *kset_create_and_add(const char *name, | 873 | struct kset *kset_create_and_add(const char *name, |
835 | struct kset_uevent_ops *uevent_ops, | 874 | const struct kset_uevent_ops *uevent_ops, |
836 | struct kobject *parent_kobj) | 875 | struct kobject *parent_kobj) |
837 | { | 876 | { |
838 | struct kset *kset; | 877 | struct kset *kset; |
@@ -850,6 +889,121 @@ struct kset *kset_create_and_add(const char *name, | |||
850 | } | 889 | } |
851 | EXPORT_SYMBOL_GPL(kset_create_and_add); | 890 | EXPORT_SYMBOL_GPL(kset_create_and_add); |
852 | 891 | ||
892 | |||
893 | static DEFINE_SPINLOCK(kobj_ns_type_lock); | ||
894 | static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES]; | ||
895 | |||
896 | int kobj_ns_type_register(const struct kobj_ns_type_operations *ops) | ||
897 | { | ||
898 | enum kobj_ns_type type = ops->type; | ||
899 | int error; | ||
900 | |||
901 | spin_lock(&kobj_ns_type_lock); | ||
902 | |||
903 | error = -EINVAL; | ||
904 | if (type >= KOBJ_NS_TYPES) | ||
905 | goto out; | ||
906 | |||
907 | error = -EINVAL; | ||
908 | if (type <= KOBJ_NS_TYPE_NONE) | ||
909 | goto out; | ||
910 | |||
911 | error = -EBUSY; | ||
912 | if (kobj_ns_ops_tbl[type]) | ||
913 | goto out; | ||
914 | |||
915 | error = 0; | ||
916 | kobj_ns_ops_tbl[type] = ops; | ||
917 | |||
918 | out: | ||
919 | spin_unlock(&kobj_ns_type_lock); | ||
920 | return error; | ||
921 | } | ||
922 | |||
923 | int kobj_ns_type_registered(enum kobj_ns_type type) | ||
924 | { | ||
925 | int registered = 0; | ||
926 | |||
927 | spin_lock(&kobj_ns_type_lock); | ||
928 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES)) | ||
929 | registered = kobj_ns_ops_tbl[type] != NULL; | ||
930 | spin_unlock(&kobj_ns_type_lock); | ||
931 | |||
932 | return registered; | ||
933 | } | ||
934 | |||
935 | const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent) | ||
936 | { | ||
937 | const struct kobj_ns_type_operations *ops = NULL; | ||
938 | |||
939 | if (parent && parent->ktype->child_ns_type) | ||
940 | ops = parent->ktype->child_ns_type(parent); | ||
941 | |||
942 | return ops; | ||
943 | } | ||
944 | |||
945 | const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj) | ||
946 | { | ||
947 | return kobj_child_ns_ops(kobj->parent); | ||
948 | } | ||
949 | |||
950 | |||
951 | const void *kobj_ns_current(enum kobj_ns_type type) | ||
952 | { | ||
953 | const void *ns = NULL; | ||
954 | |||
955 | spin_lock(&kobj_ns_type_lock); | ||
956 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
957 | kobj_ns_ops_tbl[type]) | ||
958 | ns = kobj_ns_ops_tbl[type]->current_ns(); | ||
959 | spin_unlock(&kobj_ns_type_lock); | ||
960 | |||
961 | return ns; | ||
962 | } | ||
963 | |||
964 | const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk) | ||
965 | { | ||
966 | const void *ns = NULL; | ||
967 | |||
968 | spin_lock(&kobj_ns_type_lock); | ||
969 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
970 | kobj_ns_ops_tbl[type]) | ||
971 | ns = kobj_ns_ops_tbl[type]->netlink_ns(sk); | ||
972 | spin_unlock(&kobj_ns_type_lock); | ||
973 | |||
974 | return ns; | ||
975 | } | ||
976 | |||
977 | const void *kobj_ns_initial(enum kobj_ns_type type) | ||
978 | { | ||
979 | const void *ns = NULL; | ||
980 | |||
981 | spin_lock(&kobj_ns_type_lock); | ||
982 | if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) && | ||
983 | kobj_ns_ops_tbl[type]) | ||
984 | ns = kobj_ns_ops_tbl[type]->initial_ns(); | ||
985 | spin_unlock(&kobj_ns_type_lock); | ||
986 | |||
987 | return ns; | ||
988 | } | ||
989 | |||
990 | /* | ||
991 | * kobj_ns_exit - invalidate a namespace tag | ||
992 | * | ||
993 | * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET) | ||
994 | * @ns: the actual namespace being invalidated | ||
995 | * | ||
996 | * This is called when a tag is no longer valid. For instance, | ||
997 | * when a network namespace exits, it uses this helper to | ||
998 | * make sure no sb's sysfs_info points to the now-invalidated | ||
999 | * netns. | ||
1000 | */ | ||
1001 | void kobj_ns_exit(enum kobj_ns_type type, const void *ns) | ||
1002 | { | ||
1003 | sysfs_exit_ns(type, ns); | ||
1004 | } | ||
1005 | |||
1006 | |||
853 | EXPORT_SYMBOL(kobject_get); | 1007 | EXPORT_SYMBOL(kobject_get); |
854 | EXPORT_SYMBOL(kobject_put); | 1008 | EXPORT_SYMBOL(kobject_put); |
855 | EXPORT_SYMBOL(kobject_del); | 1009 | EXPORT_SYMBOL(kobject_del); |