aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2011-10-20 00:28:46 -0400
committerDavid S. Miller <davem@davemloft.net>2011-10-21 02:53:07 -0400
commit9bf1907f4293d61d5a283d18c4ad28d048261797 (patch)
treea234645761a946931ae3c0e3ba1088ebec455325 /drivers/net/macvtap.c
parent2259fef0bb80a8fc842b5690b89a640464df2859 (diff)
macvtap: Rewrite macvtap_newlink so the error handling works.
Place macvlan_common_newlink at the end of macvtap_newlink because failing in newlink after registering your network device is not supported. Move device_create into a netdevice creation notifier. The network device notifier is the only hook that is called after the network device has been registered with the device layer and before register_network_device returns success. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c73
1 files changed, 49 insertions, 24 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 515aa873929e..25689e9df3b7 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -280,34 +280,16 @@ static int macvtap_newlink(struct net *src_net,
280 struct nlattr *tb[], 280 struct nlattr *tb[],
281 struct nlattr *data[]) 281 struct nlattr *data[])
282{ 282{
283 struct device *classdev; 283 /* Don't put anything that may fail after macvlan_common_newlink
284 dev_t devt; 284 * because we can't undo what it does.
285 int err; 285 */
286 286 return macvlan_common_newlink(src_net, dev, tb, data,
287 err = macvlan_common_newlink(src_net, dev, tb, data, 287 macvtap_receive, macvtap_forward);
288 macvtap_receive, macvtap_forward);
289 if (err)
290 goto out;
291
292 devt = MKDEV(MAJOR(macvtap_major), dev->ifindex);
293
294 classdev = device_create(macvtap_class, &dev->dev, devt,
295 dev, "tap%d", dev->ifindex);
296 if (IS_ERR(classdev)) {
297 err = PTR_ERR(classdev);
298 macvtap_del_queues(dev);
299 }
300
301out:
302 return err;
303} 288}
304 289
305static void macvtap_dellink(struct net_device *dev, 290static void macvtap_dellink(struct net_device *dev,
306 struct list_head *head) 291 struct list_head *head)
307{ 292{
308 device_destroy(macvtap_class,
309 MKDEV(MAJOR(macvtap_major), dev->ifindex));
310
311 macvtap_del_queues(dev); 293 macvtap_del_queues(dev);
312 macvlan_dellink(dev, head); 294 macvlan_dellink(dev, head);
313} 295}
@@ -975,6 +957,42 @@ struct socket *macvtap_get_socket(struct file *file)
975} 957}
976EXPORT_SYMBOL_GPL(macvtap_get_socket); 958EXPORT_SYMBOL_GPL(macvtap_get_socket);
977 959
960static int macvtap_device_event(struct notifier_block *unused,
961 unsigned long event, void *ptr)
962{
963 struct net_device *dev = ptr;
964 struct device *classdev;
965 dev_t devt;
966
967 if (dev->rtnl_link_ops != &macvtap_link_ops)
968 return NOTIFY_DONE;
969
970
971 switch (event) {
972 case NETDEV_REGISTER:
973 /* Create the device node here after the network device has
974 * been registered but before register_netdevice has
975 * finished running.
976 */
977 devt = MKDEV(MAJOR(macvtap_major), dev->ifindex);
978 classdev = device_create(macvtap_class, &dev->dev, devt,
979 dev, "tap%d", dev->ifindex);
980 if (IS_ERR(classdev))
981 return notifier_from_errno(PTR_ERR(classdev));
982 break;
983 case NETDEV_UNREGISTER:
984 devt = MKDEV(MAJOR(macvtap_major), dev->ifindex);
985 device_destroy(macvtap_class, devt);
986 break;
987 }
988
989 return NOTIFY_DONE;
990}
991
992static struct notifier_block macvtap_notifier_block __read_mostly = {
993 .notifier_call = macvtap_device_event,
994};
995
978static int macvtap_init(void) 996static int macvtap_init(void)
979{ 997{
980 int err; 998 int err;
@@ -995,12 +1013,18 @@ static int macvtap_init(void)
995 goto out3; 1013 goto out3;
996 } 1014 }
997 1015
998 err = macvlan_link_register(&macvtap_link_ops); 1016 err = register_netdevice_notifier(&macvtap_notifier_block);
999 if (err) 1017 if (err)
1000 goto out4; 1018 goto out4;
1001 1019
1020 err = macvlan_link_register(&macvtap_link_ops);
1021 if (err)
1022 goto out5;
1023
1002 return 0; 1024 return 0;
1003 1025
1026out5:
1027 unregister_netdevice_notifier(&macvtap_notifier_block);
1004out4: 1028out4:
1005 class_unregister(macvtap_class); 1029 class_unregister(macvtap_class);
1006out3: 1030out3:
@@ -1015,6 +1039,7 @@ module_init(macvtap_init);
1015static void macvtap_exit(void) 1039static void macvtap_exit(void)
1016{ 1040{
1017 rtnl_link_unregister(&macvtap_link_ops); 1041 rtnl_link_unregister(&macvtap_link_ops);
1042 unregister_netdevice_notifier(&macvtap_notifier_block);
1018 class_unregister(macvtap_class); 1043 class_unregister(macvtap_class);
1019 cdev_del(&macvtap_cdev); 1044 cdev_del(&macvtap_cdev);
1020 unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS); 1045 unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);