aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 13:48:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-21 13:48:32 -0400
commitd6fb1db02e02aea98f2d7e121fd30e24c84639d6 (patch)
tree865546f0388c40d52cf98febe2c6d21039915ea2 /lib
parentb4e6b09738fde057ce885703705f71cc953d0512 (diff)
parenta1b3f594dc5faab91d3a218c7019e9b5edd9fe1a (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (38 commits) net: Expose all network devices in a namespaces in sysfs hotplug: netns aware uevent_helper kobj: Send hotplug events in the proper namespace. netlink: Implment netlink_broadcast_filtered net/sysfs: Fix the bitrot in network device kobject namespace support netns: Teach network device kobjects which namespace they are in. kobject: Send hotplug events in all network namespaces driver-core: fix Typo in drivers/base/core.c for CONFIG_MODULE pci: check caps from sysfs file open to read device dependent config space sysfs: add struct file* to bin_attr callbacks sysfs: Remove usage of S_BIAS to avoid merge conflict with the vfs tree sysfs: Don't use enums in inline function declaration. sysfs-namespaces: add a high-level Documentation file sysfs: Comment sysfs directory tagging logic driver core: Implement ns directory support for device classes. sysfs: Implement sysfs_delete_link sysfs: Add support for tagged directories with untagged members. sysfs: Implement sysfs tagged directory support. kobj: Add basic infrastructure for dealing with namespaces. sysfs: Remove double free sysfs_get_sb ...
Diffstat (limited to 'lib')
-rw-r--r--lib/kobject.c115
-rw-r--r--lib/kobject_uevent.c109
-rw-r--r--lib/kref.c15
3 files changed, 214 insertions, 25 deletions
diff --git a/lib/kobject.c b/lib/kobject.c
index 8115eb1bbf4d..f07c57252e82 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -850,6 +850,121 @@ struct kset *kset_create_and_add(const char *name,
850} 850}
851EXPORT_SYMBOL_GPL(kset_create_and_add); 851EXPORT_SYMBOL_GPL(kset_create_and_add);
852 852
853
854static DEFINE_SPINLOCK(kobj_ns_type_lock);
855static const struct kobj_ns_type_operations *kobj_ns_ops_tbl[KOBJ_NS_TYPES];
856
857int kobj_ns_type_register(const struct kobj_ns_type_operations *ops)
858{
859 enum kobj_ns_type type = ops->type;
860 int error;
861
862 spin_lock(&kobj_ns_type_lock);
863
864 error = -EINVAL;
865 if (type >= KOBJ_NS_TYPES)
866 goto out;
867
868 error = -EINVAL;
869 if (type <= KOBJ_NS_TYPE_NONE)
870 goto out;
871
872 error = -EBUSY;
873 if (kobj_ns_ops_tbl[type])
874 goto out;
875
876 error = 0;
877 kobj_ns_ops_tbl[type] = ops;
878
879out:
880 spin_unlock(&kobj_ns_type_lock);
881 return error;
882}
883
884int kobj_ns_type_registered(enum kobj_ns_type type)
885{
886 int registered = 0;
887
888 spin_lock(&kobj_ns_type_lock);
889 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES))
890 registered = kobj_ns_ops_tbl[type] != NULL;
891 spin_unlock(&kobj_ns_type_lock);
892
893 return registered;
894}
895
896const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent)
897{
898 const struct kobj_ns_type_operations *ops = NULL;
899
900 if (parent && parent->ktype->child_ns_type)
901 ops = parent->ktype->child_ns_type(parent);
902
903 return ops;
904}
905
906const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
907{
908 return kobj_child_ns_ops(kobj->parent);
909}
910
911
912const void *kobj_ns_current(enum kobj_ns_type type)
913{
914 const void *ns = NULL;
915
916 spin_lock(&kobj_ns_type_lock);
917 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
918 kobj_ns_ops_tbl[type])
919 ns = kobj_ns_ops_tbl[type]->current_ns();
920 spin_unlock(&kobj_ns_type_lock);
921
922 return ns;
923}
924
925const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk)
926{
927 const void *ns = NULL;
928
929 spin_lock(&kobj_ns_type_lock);
930 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
931 kobj_ns_ops_tbl[type])
932 ns = kobj_ns_ops_tbl[type]->netlink_ns(sk);
933 spin_unlock(&kobj_ns_type_lock);
934
935 return ns;
936}
937
938const void *kobj_ns_initial(enum kobj_ns_type type)
939{
940 const void *ns = NULL;
941
942 spin_lock(&kobj_ns_type_lock);
943 if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
944 kobj_ns_ops_tbl[type])
945 ns = kobj_ns_ops_tbl[type]->initial_ns();
946 spin_unlock(&kobj_ns_type_lock);
947
948 return ns;
949}
950
951/*
952 * kobj_ns_exit - invalidate a namespace tag
953 *
954 * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET)
955 * @ns: the actual namespace being invalidated
956 *
957 * This is called when a tag is no longer valid. For instance,
958 * when a network namespace exits, it uses this helper to
959 * make sure no sb's sysfs_info points to the now-invalidated
960 * netns.
961 */
962void kobj_ns_exit(enum kobj_ns_type type, const void *ns)
963{
964 sysfs_exit_ns(type, ns);
965}
966
967
853EXPORT_SYMBOL(kobject_get); 968EXPORT_SYMBOL(kobject_get);
854EXPORT_SYMBOL(kobject_put); 969EXPORT_SYMBOL(kobject_put);
855EXPORT_SYMBOL(kobject_del); 970EXPORT_SYMBOL(kobject_del);
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 7b48d44ced6e..59c15511d58a 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -19,18 +19,24 @@
19#include <linux/kobject.h> 19#include <linux/kobject.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/slab.h> 21#include <linux/slab.h>
22 22#include <linux/user_namespace.h>
23#include <linux/socket.h> 23#include <linux/socket.h>
24#include <linux/skbuff.h> 24#include <linux/skbuff.h>
25#include <linux/netlink.h> 25#include <linux/netlink.h>
26#include <net/sock.h> 26#include <net/sock.h>
27#include <net/net_namespace.h>
27 28
28 29
29u64 uevent_seqnum; 30u64 uevent_seqnum;
30char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; 31char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
31static DEFINE_SPINLOCK(sequence_lock); 32static DEFINE_SPINLOCK(sequence_lock);
32#if defined(CONFIG_NET) 33#ifdef CONFIG_NET
33static struct sock *uevent_sock; 34struct uevent_sock {
35 struct list_head list;
36 struct sock *sk;
37};
38static LIST_HEAD(uevent_sock_list);
39static DEFINE_MUTEX(uevent_sock_mutex);
34#endif 40#endif
35 41
36/* the strings here must match the enum in include/linux/kobject.h */ 42/* the strings here must match the enum in include/linux/kobject.h */
@@ -77,6 +83,37 @@ out:
77 return ret; 83 return ret;
78} 84}
79 85
86static int kobj_bcast_filter(struct sock *dsk, struct sk_buff *skb, void *data)
87{
88 struct kobject *kobj = data;
89 const struct kobj_ns_type_operations *ops;
90
91 ops = kobj_ns_ops(kobj);
92 if (ops) {
93 const void *sock_ns, *ns;
94 ns = kobj->ktype->namespace(kobj);
95 sock_ns = ops->netlink_ns(dsk);
96 return sock_ns != ns;
97 }
98
99 return 0;
100}
101
102static int kobj_usermode_filter(struct kobject *kobj)
103{
104 const struct kobj_ns_type_operations *ops;
105
106 ops = kobj_ns_ops(kobj);
107 if (ops) {
108 const void *init_ns, *ns;
109 ns = kobj->ktype->namespace(kobj);
110 init_ns = ops->initial_ns();
111 return ns != init_ns;
112 }
113
114 return 0;
115}
116
80/** 117/**
81 * kobject_uevent_env - send an uevent with environmental data 118 * kobject_uevent_env - send an uevent with environmental data
82 * 119 *
@@ -100,6 +137,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
100 u64 seq; 137 u64 seq;
101 int i = 0; 138 int i = 0;
102 int retval = 0; 139 int retval = 0;
140#ifdef CONFIG_NET
141 struct uevent_sock *ue_sk;
142#endif
103 143
104 pr_debug("kobject: '%s' (%p): %s\n", 144 pr_debug("kobject: '%s' (%p): %s\n",
105 kobject_name(kobj), kobj, __func__); 145 kobject_name(kobj), kobj, __func__);
@@ -211,7 +251,9 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
211 251
212#if defined(CONFIG_NET) 252#if defined(CONFIG_NET)
213 /* send netlink message */ 253 /* send netlink message */
214 if (uevent_sock) { 254 mutex_lock(&uevent_sock_mutex);
255 list_for_each_entry(ue_sk, &uevent_sock_list, list) {
256 struct sock *uevent_sock = ue_sk->sk;
215 struct sk_buff *skb; 257 struct sk_buff *skb;
216 size_t len; 258 size_t len;
217 259
@@ -233,18 +275,21 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
233 } 275 }
234 276
235 NETLINK_CB(skb).dst_group = 1; 277 NETLINK_CB(skb).dst_group = 1;
236 retval = netlink_broadcast(uevent_sock, skb, 0, 1, 278 retval = netlink_broadcast_filtered(uevent_sock, skb,
237 GFP_KERNEL); 279 0, 1, GFP_KERNEL,
280 kobj_bcast_filter,
281 kobj);
238 /* ENOBUFS should be handled in userspace */ 282 /* ENOBUFS should be handled in userspace */
239 if (retval == -ENOBUFS) 283 if (retval == -ENOBUFS)
240 retval = 0; 284 retval = 0;
241 } else 285 } else
242 retval = -ENOMEM; 286 retval = -ENOMEM;
243 } 287 }
288 mutex_unlock(&uevent_sock_mutex);
244#endif 289#endif
245 290
246 /* call uevent_helper, usually only enabled during early boot */ 291 /* call uevent_helper, usually only enabled during early boot */
247 if (uevent_helper[0]) { 292 if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
248 char *argv [3]; 293 char *argv [3];
249 294
250 argv [0] = uevent_helper; 295 argv [0] = uevent_helper;
@@ -320,18 +365,58 @@ int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
320EXPORT_SYMBOL_GPL(add_uevent_var); 365EXPORT_SYMBOL_GPL(add_uevent_var);
321 366
322#if defined(CONFIG_NET) 367#if defined(CONFIG_NET)
323static int __init kobject_uevent_init(void) 368static int uevent_net_init(struct net *net)
324{ 369{
325 uevent_sock = netlink_kernel_create(&init_net, NETLINK_KOBJECT_UEVENT, 370 struct uevent_sock *ue_sk;
326 1, NULL, NULL, THIS_MODULE); 371
327 if (!uevent_sock) { 372 ue_sk = kzalloc(sizeof(*ue_sk), GFP_KERNEL);
373 if (!ue_sk)
374 return -ENOMEM;
375
376 ue_sk->sk = netlink_kernel_create(net, NETLINK_KOBJECT_UEVENT,
377 1, NULL, NULL, THIS_MODULE);
378 if (!ue_sk->sk) {
328 printk(KERN_ERR 379 printk(KERN_ERR
329 "kobject_uevent: unable to create netlink socket!\n"); 380 "kobject_uevent: unable to create netlink socket!\n");
330 return -ENODEV; 381 return -ENODEV;
331 } 382 }
332 netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV); 383 mutex_lock(&uevent_sock_mutex);
384 list_add_tail(&ue_sk->list, &uevent_sock_list);
385 mutex_unlock(&uevent_sock_mutex);
333 return 0; 386 return 0;
334} 387}
335 388
389static void uevent_net_exit(struct net *net)
390{
391 struct uevent_sock *ue_sk;
392
393 mutex_lock(&uevent_sock_mutex);
394 list_for_each_entry(ue_sk, &uevent_sock_list, list) {
395 if (sock_net(ue_sk->sk) == net)
396 goto found;
397 }
398 mutex_unlock(&uevent_sock_mutex);
399 return;
400
401found:
402 list_del(&ue_sk->list);
403 mutex_unlock(&uevent_sock_mutex);
404
405 netlink_kernel_release(ue_sk->sk);
406 kfree(ue_sk);
407}
408
409static struct pernet_operations uevent_net_ops = {
410 .init = uevent_net_init,
411 .exit = uevent_net_exit,
412};
413
414static int __init kobject_uevent_init(void)
415{
416 netlink_set_nonroot(NETLINK_KOBJECT_UEVENT, NL_NONROOT_RECV);
417 return register_pernet_subsys(&uevent_net_ops);
418}
419
420
336postcore_initcall(kobject_uevent_init); 421postcore_initcall(kobject_uevent_init);
337#endif 422#endif
diff --git a/lib/kref.c b/lib/kref.c
index 6d19f690380b..d3d227a08a4b 100644
--- a/lib/kref.c
+++ b/lib/kref.c
@@ -16,23 +16,13 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17 17
18/** 18/**
19 * kref_set - initialize object and set refcount to requested number.
20 * @kref: object in question.
21 * @num: initial reference counter
22 */
23void kref_set(struct kref *kref, int num)
24{
25 atomic_set(&kref->refcount, num);
26 smp_mb();
27}
28
29/**
30 * kref_init - initialize object. 19 * kref_init - initialize object.
31 * @kref: object in question. 20 * @kref: object in question.
32 */ 21 */
33void kref_init(struct kref *kref) 22void kref_init(struct kref *kref)
34{ 23{
35 kref_set(kref, 1); 24 atomic_set(&kref->refcount, 1);
25 smp_mb();
36} 26}
37 27
38/** 28/**
@@ -72,7 +62,6 @@ int kref_put(struct kref *kref, void (*release)(struct kref *kref))
72 return 0; 62 return 0;
73} 63}
74 64
75EXPORT_SYMBOL(kref_set);
76EXPORT_SYMBOL(kref_init); 65EXPORT_SYMBOL(kref_init);
77EXPORT_SYMBOL(kref_get); 66EXPORT_SYMBOL(kref_get);
78EXPORT_SYMBOL(kref_put); 67EXPORT_SYMBOL(kref_put);