diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 2d615a93685e8d..02c0ae58b9db7c 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -772,9 +772,13 @@ int bond_create_sysfs(struct bond_net *bn) { int ret; + bn->skip_destroy_class = false; bn->class_attr_bonding_masters = class_attr_bonding_masters; sysfs_attr_init(&bn->class_attr_bonding_masters.attr); + rtnl_lock(); + if (netdev_class_has_file_ns("bonding_masters", bn->net)) + goto err; ret = netdev_class_create_file_ns(&bn->class_attr_bonding_masters, bn->net); /* Permit multiple loads of the module by ignoring failures to @@ -788,13 +792,16 @@ int bond_create_sysfs(struct bond_net *bn) * configure multiple bonding devices. */ if (ret == -EEXIST) { +err: /* Is someone being kinky and naming a device bonding_master? */ if (__dev_get_by_name(bn->net, class_attr_bonding_masters.attr.name)) pr_err("network device named %s already exists in sysfs\n", class_attr_bonding_masters.attr.name); ret = 0; + bn->skip_destroy_class = true; } + rtnl_unlock(); return ret; @@ -803,7 +810,11 @@ int bond_create_sysfs(struct bond_net *bn) /* Remove /sys/class/net/bonding_masters. */ void bond_destroy_sysfs(struct bond_net *bn) { - netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, bn->net); + rtnl_lock(); + if (!bn->skip_destroy_class) + netdev_class_remove_file_ns(&bn->class_attr_bonding_masters, + bn->net); + rtnl_unlock(); } /* Initialize sysfs for each bond. This sets up and registers diff --git a/include/net/bonding.h b/include/net/bonding.h index 3d56b026bb9e77..725e26c4962cee 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -607,6 +607,7 @@ struct bond_net { struct proc_dir_entry *proc_dir; #endif struct class_attribute class_attr_bonding_masters; + bool skip_destroy_class; }; int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave); diff --git a/net/core/dev.c b/net/core/dev.c index 402a986659cf5d..8a4d9a23fb63e0 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10037,6 +10037,10 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char goto out; } + err = -EEXIST; + if (netdev_class_has_file_ns(dev->name, net)) + goto out; + /* * And now a mini version of register_netdevice unregister_netdevice. */