diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:48:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 13:48:32 -0400 |
commit | d6fb1db02e02aea98f2d7e121fd30e24c84639d6 (patch) | |
tree | 865546f0388c40d52cf98febe2c6d21039915ea2 /net | |
parent | b4e6b09738fde057ce885703705f71cc953d0512 (diff) | |
parent | a1b3f594dc5faab91d3a218c7019e9b5edd9fe1a (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 'net')
-rw-r--r-- | net/bridge/br_sysfs_br.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 28 | ||||
-rw-r--r-- | net/core/net-sysfs.c | 63 | ||||
-rw-r--r-- | net/core/net-sysfs.h | 1 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 21 |
5 files changed, 72 insertions, 43 deletions
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index dd321e39e621..486b8f3861d2 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -659,7 +659,7 @@ static struct attribute_group bridge_group = { | |||
659 | * | 659 | * |
660 | * Returns the number of bytes read. | 660 | * Returns the number of bytes read. |
661 | */ | 661 | */ |
662 | static ssize_t brforward_read(struct kobject *kobj, | 662 | static ssize_t brforward_read(struct file *filp, struct kobject *kobj, |
663 | struct bin_attribute *bin_attr, | 663 | struct bin_attribute *bin_attr, |
664 | char *buf, loff_t off, size_t count) | 664 | char *buf, loff_t off, size_t count) |
665 | { | 665 | { |
diff --git a/net/core/dev.c b/net/core/dev.c index 6c820650b80f..d273e4e3ecdc 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1002,15 +1002,10 @@ int dev_change_name(struct net_device *dev, const char *newname) | |||
1002 | return err; | 1002 | return err; |
1003 | 1003 | ||
1004 | rollback: | 1004 | rollback: |
1005 | /* For now only devices in the initial network namespace | 1005 | ret = device_rename(&dev->dev, dev->name); |
1006 | * are in sysfs. | 1006 | if (ret) { |
1007 | */ | 1007 | memcpy(dev->name, oldname, IFNAMSIZ); |
1008 | if (net_eq(net, &init_net)) { | 1008 | return ret; |
1009 | ret = device_rename(&dev->dev, dev->name); | ||
1010 | if (ret) { | ||
1011 | memcpy(dev->name, oldname, IFNAMSIZ); | ||
1012 | return ret; | ||
1013 | } | ||
1014 | } | 1009 | } |
1015 | 1010 | ||
1016 | write_lock_bh(&dev_base_lock); | 1011 | write_lock_bh(&dev_base_lock); |
@@ -4994,8 +4989,6 @@ int register_netdevice(struct net_device *dev) | |||
4994 | if (dev->features & NETIF_F_SG) | 4989 | if (dev->features & NETIF_F_SG) |
4995 | dev->features |= NETIF_F_GSO; | 4990 | dev->features |= NETIF_F_GSO; |
4996 | 4991 | ||
4997 | netdev_initialize_kobject(dev); | ||
4998 | |||
4999 | ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); | 4992 | ret = call_netdevice_notifiers(NETDEV_POST_INIT, dev); |
5000 | ret = notifier_to_errno(ret); | 4993 | ret = notifier_to_errno(ret); |
5001 | if (ret) | 4994 | if (ret) |
@@ -5547,15 +5540,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5547 | if (dev->features & NETIF_F_NETNS_LOCAL) | 5540 | if (dev->features & NETIF_F_NETNS_LOCAL) |
5548 | goto out; | 5541 | goto out; |
5549 | 5542 | ||
5550 | #ifdef CONFIG_SYSFS | ||
5551 | /* Don't allow real devices to be moved when sysfs | ||
5552 | * is enabled. | ||
5553 | */ | ||
5554 | err = -EINVAL; | ||
5555 | if (dev->dev.parent) | ||
5556 | goto out; | ||
5557 | #endif | ||
5558 | |||
5559 | /* Ensure the device has been registrered */ | 5543 | /* Ensure the device has been registrered */ |
5560 | err = -EINVAL; | 5544 | err = -EINVAL; |
5561 | if (dev->reg_state != NETREG_REGISTERED) | 5545 | if (dev->reg_state != NETREG_REGISTERED) |
@@ -5606,8 +5590,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5606 | dev_uc_flush(dev); | 5590 | dev_uc_flush(dev); |
5607 | dev_mc_flush(dev); | 5591 | dev_mc_flush(dev); |
5608 | 5592 | ||
5609 | netdev_unregister_kobject(dev); | ||
5610 | |||
5611 | /* Actually switch the network namespace */ | 5593 | /* Actually switch the network namespace */ |
5612 | dev_net_set(dev, net); | 5594 | dev_net_set(dev, net); |
5613 | 5595 | ||
@@ -5620,7 +5602,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
5620 | } | 5602 | } |
5621 | 5603 | ||
5622 | /* Fixup kobjects */ | 5604 | /* Fixup kobjects */ |
5623 | err = netdev_register_kobject(dev); | 5605 | err = device_rename(&dev->dev, dev->name); |
5624 | WARN_ON(err); | 5606 | WARN_ON(err); |
5625 | 5607 | ||
5626 | /* Add the device back in the hashes */ | 5608 | /* Add the device back in the hashes */ |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c57c4b228bb5..99e7052d7323 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -14,7 +14,9 @@ | |||
14 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/nsproxy.h> | ||
17 | #include <net/sock.h> | 18 | #include <net/sock.h> |
19 | #include <net/net_namespace.h> | ||
18 | #include <linux/rtnetlink.h> | 20 | #include <linux/rtnetlink.h> |
19 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
20 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
@@ -467,6 +469,7 @@ static struct attribute_group wireless_group = { | |||
467 | .attrs = wireless_attrs, | 469 | .attrs = wireless_attrs, |
468 | }; | 470 | }; |
469 | #endif | 471 | #endif |
472 | #endif /* CONFIG_SYSFS */ | ||
470 | 473 | ||
471 | #ifdef CONFIG_RPS | 474 | #ifdef CONFIG_RPS |
472 | /* | 475 | /* |
@@ -766,7 +769,38 @@ static void rx_queue_remove_kobjects(struct net_device *net) | |||
766 | kset_unregister(net->queues_kset); | 769 | kset_unregister(net->queues_kset); |
767 | } | 770 | } |
768 | #endif /* CONFIG_RPS */ | 771 | #endif /* CONFIG_RPS */ |
769 | #endif /* CONFIG_SYSFS */ | 772 | |
773 | static const void *net_current_ns(void) | ||
774 | { | ||
775 | return current->nsproxy->net_ns; | ||
776 | } | ||
777 | |||
778 | static const void *net_initial_ns(void) | ||
779 | { | ||
780 | return &init_net; | ||
781 | } | ||
782 | |||
783 | static const void *net_netlink_ns(struct sock *sk) | ||
784 | { | ||
785 | return sock_net(sk); | ||
786 | } | ||
787 | |||
788 | static struct kobj_ns_type_operations net_ns_type_operations = { | ||
789 | .type = KOBJ_NS_TYPE_NET, | ||
790 | .current_ns = net_current_ns, | ||
791 | .netlink_ns = net_netlink_ns, | ||
792 | .initial_ns = net_initial_ns, | ||
793 | }; | ||
794 | |||
795 | static void net_kobj_ns_exit(struct net *net) | ||
796 | { | ||
797 | kobj_ns_exit(KOBJ_NS_TYPE_NET, net); | ||
798 | } | ||
799 | |||
800 | static struct pernet_operations kobj_net_ops = { | ||
801 | .exit = net_kobj_ns_exit, | ||
802 | }; | ||
803 | |||
770 | 804 | ||
771 | #ifdef CONFIG_HOTPLUG | 805 | #ifdef CONFIG_HOTPLUG |
772 | static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) | 806 | static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) |
@@ -774,9 +808,6 @@ static int netdev_uevent(struct device *d, struct kobj_uevent_env *env) | |||
774 | struct net_device *dev = to_net_dev(d); | 808 | struct net_device *dev = to_net_dev(d); |
775 | int retval; | 809 | int retval; |
776 | 810 | ||
777 | if (!net_eq(dev_net(dev), &init_net)) | ||
778 | return 0; | ||
779 | |||
780 | /* pass interface to uevent. */ | 811 | /* pass interface to uevent. */ |
781 | retval = add_uevent_var(env, "INTERFACE=%s", dev->name); | 812 | retval = add_uevent_var(env, "INTERFACE=%s", dev->name); |
782 | if (retval) | 813 | if (retval) |
@@ -806,6 +837,13 @@ static void netdev_release(struct device *d) | |||
806 | kfree((char *)dev - dev->padded); | 837 | kfree((char *)dev - dev->padded); |
807 | } | 838 | } |
808 | 839 | ||
840 | static const void *net_namespace(struct device *d) | ||
841 | { | ||
842 | struct net_device *dev; | ||
843 | dev = container_of(d, struct net_device, dev); | ||
844 | return dev_net(dev); | ||
845 | } | ||
846 | |||
809 | static struct class net_class = { | 847 | static struct class net_class = { |
810 | .name = "net", | 848 | .name = "net", |
811 | .dev_release = netdev_release, | 849 | .dev_release = netdev_release, |
@@ -815,6 +853,8 @@ static struct class net_class = { | |||
815 | #ifdef CONFIG_HOTPLUG | 853 | #ifdef CONFIG_HOTPLUG |
816 | .dev_uevent = netdev_uevent, | 854 | .dev_uevent = netdev_uevent, |
817 | #endif | 855 | #endif |
856 | .ns_type = &net_ns_type_operations, | ||
857 | .namespace = net_namespace, | ||
818 | }; | 858 | }; |
819 | 859 | ||
820 | /* Delete sysfs entries but hold kobject reference until after all | 860 | /* Delete sysfs entries but hold kobject reference until after all |
@@ -826,9 +866,6 @@ void netdev_unregister_kobject(struct net_device * net) | |||
826 | 866 | ||
827 | kobject_get(&dev->kobj); | 867 | kobject_get(&dev->kobj); |
828 | 868 | ||
829 | if (!net_eq(dev_net(net), &init_net)) | ||
830 | return; | ||
831 | |||
832 | #ifdef CONFIG_RPS | 869 | #ifdef CONFIG_RPS |
833 | rx_queue_remove_kobjects(net); | 870 | rx_queue_remove_kobjects(net); |
834 | #endif | 871 | #endif |
@@ -843,6 +880,7 @@ int netdev_register_kobject(struct net_device *net) | |||
843 | const struct attribute_group **groups = net->sysfs_groups; | 880 | const struct attribute_group **groups = net->sysfs_groups; |
844 | int error = 0; | 881 | int error = 0; |
845 | 882 | ||
883 | device_initialize(dev); | ||
846 | dev->class = &net_class; | 884 | dev->class = &net_class; |
847 | dev->platform_data = net; | 885 | dev->platform_data = net; |
848 | dev->groups = groups; | 886 | dev->groups = groups; |
@@ -865,9 +903,6 @@ int netdev_register_kobject(struct net_device *net) | |||
865 | #endif | 903 | #endif |
866 | #endif /* CONFIG_SYSFS */ | 904 | #endif /* CONFIG_SYSFS */ |
867 | 905 | ||
868 | if (!net_eq(dev_net(net), &init_net)) | ||
869 | return 0; | ||
870 | |||
871 | error = device_add(dev); | 906 | error = device_add(dev); |
872 | if (error) | 907 | if (error) |
873 | return error; | 908 | return error; |
@@ -896,13 +931,9 @@ void netdev_class_remove_file(struct class_attribute *class_attr) | |||
896 | EXPORT_SYMBOL(netdev_class_create_file); | 931 | EXPORT_SYMBOL(netdev_class_create_file); |
897 | EXPORT_SYMBOL(netdev_class_remove_file); | 932 | EXPORT_SYMBOL(netdev_class_remove_file); |
898 | 933 | ||
899 | void netdev_initialize_kobject(struct net_device *net) | ||
900 | { | ||
901 | struct device *device = &(net->dev); | ||
902 | device_initialize(device); | ||
903 | } | ||
904 | |||
905 | int netdev_kobject_init(void) | 934 | int netdev_kobject_init(void) |
906 | { | 935 | { |
936 | kobj_ns_type_register(&net_ns_type_operations); | ||
937 | register_pernet_subsys(&kobj_net_ops); | ||
907 | return class_register(&net_class); | 938 | return class_register(&net_class); |
908 | } | 939 | } |
diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h index 14e7524260b3..805555e8b187 100644 --- a/net/core/net-sysfs.h +++ b/net/core/net-sysfs.h | |||
@@ -4,5 +4,4 @@ | |||
4 | int netdev_kobject_init(void); | 4 | int netdev_kobject_init(void); |
5 | int netdev_register_kobject(struct net_device *); | 5 | int netdev_register_kobject(struct net_device *); |
6 | void netdev_unregister_kobject(struct net_device *); | 6 | void netdev_unregister_kobject(struct net_device *); |
7 | void netdev_initialize_kobject(struct net_device *); | ||
8 | #endif | 7 | #endif |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 6464a1972a69..a2eb965207d3 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -978,6 +978,8 @@ struct netlink_broadcast_data { | |||
978 | int delivered; | 978 | int delivered; |
979 | gfp_t allocation; | 979 | gfp_t allocation; |
980 | struct sk_buff *skb, *skb2; | 980 | struct sk_buff *skb, *skb2; |
981 | int (*tx_filter)(struct sock *dsk, struct sk_buff *skb, void *data); | ||
982 | void *tx_data; | ||
981 | }; | 983 | }; |
982 | 984 | ||
983 | static inline int do_one_broadcast(struct sock *sk, | 985 | static inline int do_one_broadcast(struct sock *sk, |
@@ -1020,6 +1022,9 @@ static inline int do_one_broadcast(struct sock *sk, | |||
1020 | p->failure = 1; | 1022 | p->failure = 1; |
1021 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) | 1023 | if (nlk->flags & NETLINK_BROADCAST_SEND_ERROR) |
1022 | p->delivery_failure = 1; | 1024 | p->delivery_failure = 1; |
1025 | } else if (p->tx_filter && p->tx_filter(sk, p->skb2, p->tx_data)) { | ||
1026 | kfree_skb(p->skb2); | ||
1027 | p->skb2 = NULL; | ||
1023 | } else if (sk_filter(sk, p->skb2)) { | 1028 | } else if (sk_filter(sk, p->skb2)) { |
1024 | kfree_skb(p->skb2); | 1029 | kfree_skb(p->skb2); |
1025 | p->skb2 = NULL; | 1030 | p->skb2 = NULL; |
@@ -1038,8 +1043,10 @@ out: | |||
1038 | return 0; | 1043 | return 0; |
1039 | } | 1044 | } |
1040 | 1045 | ||
1041 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | 1046 | int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid, |
1042 | u32 group, gfp_t allocation) | 1047 | u32 group, gfp_t allocation, |
1048 | int (*filter)(struct sock *dsk, struct sk_buff *skb, void *data), | ||
1049 | void *filter_data) | ||
1043 | { | 1050 | { |
1044 | struct net *net = sock_net(ssk); | 1051 | struct net *net = sock_net(ssk); |
1045 | struct netlink_broadcast_data info; | 1052 | struct netlink_broadcast_data info; |
@@ -1059,6 +1066,8 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
1059 | info.allocation = allocation; | 1066 | info.allocation = allocation; |
1060 | info.skb = skb; | 1067 | info.skb = skb; |
1061 | info.skb2 = NULL; | 1068 | info.skb2 = NULL; |
1069 | info.tx_filter = filter; | ||
1070 | info.tx_data = filter_data; | ||
1062 | 1071 | ||
1063 | /* While we sleep in clone, do not allow to change socket list */ | 1072 | /* While we sleep in clone, do not allow to change socket list */ |
1064 | 1073 | ||
@@ -1083,6 +1092,14 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | |||
1083 | } | 1092 | } |
1084 | return -ESRCH; | 1093 | return -ESRCH; |
1085 | } | 1094 | } |
1095 | EXPORT_SYMBOL(netlink_broadcast_filtered); | ||
1096 | |||
1097 | int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid, | ||
1098 | u32 group, gfp_t allocation) | ||
1099 | { | ||
1100 | return netlink_broadcast_filtered(ssk, skb, pid, group, allocation, | ||
1101 | NULL, NULL); | ||
1102 | } | ||
1086 | EXPORT_SYMBOL(netlink_broadcast); | 1103 | EXPORT_SYMBOL(netlink_broadcast); |
1087 | 1104 | ||
1088 | struct netlink_set_err_data { | 1105 | struct netlink_set_err_data { |