aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kobject.c')
-rw-r--r--lib/kobject.c160
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
703struct sysfs_ops kobj_sysfs_ops = { 703const 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 */
747struct kobject *kset_find_obj(struct kset *kset, const char *name) 747struct 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 */
763struct 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
785slow_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
793unlock_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 */
791static struct kset *kset_create(const char *name, 830static 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 */
834struct kset *kset_create_and_add(const char *name, 873struct 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}
851EXPORT_SYMBOL_GPL(kset_create_and_add); 890EXPORT_SYMBOL_GPL(kset_create_and_add);
852 891
892
893static DEFINE_SPINLOCK(kobj_ns_type_lock);
894static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
895
896int 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
918out:
919 spin_unlock(&kobj_ns_type_lock);
920 return error;
921}
922
923int 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
935const 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
945const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
946{
947 return kobj_child_ns_ops(kobj->parent);
948}
949
950
951const 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
964const 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
977const 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 */
1001void kobj_ns_exit(enum kobj_ns_type type, const void *ns)
1002{
1003 sysfs_exit_ns(type, ns);
1004}
1005
1006
853EXPORT_SYMBOL(kobject_get); 1007EXPORT_SYMBOL(kobject_get);
854EXPORT_SYMBOL(kobject_put); 1008EXPORT_SYMBOL(kobject_put);
855EXPORT_SYMBOL(kobject_del); 1009EXPORT_SYMBOL(kobject_del);