return 0;
}
+/* Create a new bond based on the specified name and bonding parameters.
+ * Caller must NOT hold rtnl_lock; we need to release it here before we
+ * set up our sysfs entries.
+ */
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
+{
+ struct net_device *bond_dev;
+ int res;
+
+ rtnl_lock();
+ bond_dev = alloc_netdev(sizeof(struct bonding), name, ether_setup);
+ if (!bond_dev) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: eek! can't alloc netdev!\n",
+ name);
+ res = -ENOMEM;
+ goto out_rtnl;
+ }
+
+ /* bond_init() must be called after dev_alloc_name() (for the
+ * /proc files), but before register_netdevice(), because we
+ * need to set function pointers.
+ */
+
+ res = bond_init(bond_dev, params);
+ if (res < 0) {
+ goto out_netdev;
+ }
+
+ SET_MODULE_OWNER(bond_dev);
+
+ res = register_netdevice(bond_dev);
+ if (res < 0) {
+ goto out_bond;
+ }
+ if (newbond)
+ *newbond = bond_dev->priv;
+
+ rtnl_unlock(); /* allows sysfs registration of net device */
+ goto done;
+out_bond:
+ bond_deinit(bond_dev);
+out_netdev:
+ free_netdev(bond_dev);
+out_rtnl:
+ rtnl_unlock();
+done:
+ return res;
+}
+
static int __init bonding_init(void)
{
- struct bond_params params;
int i;
int res;
+ char new_bond_name[8]; /* Enough room for 999 bonds at init. */
printk(KERN_INFO "%s", version);
- res = bond_check_params(¶ms);
+ res = bond_check_params(&bonding_defaults);
if (res) {
- return res;
+ goto out;
}
- rtnl_lock();
-
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif
-
for (i = 0; i < max_bonds; i++) {
- struct net_device *bond_dev;
-
- bond_dev = alloc_netdev(sizeof(struct bonding), "", ether_setup);
- if (!bond_dev) {
- res = -ENOMEM;
- goto out_err;
- }
-
- res = dev_alloc_name(bond_dev, "bond%d");
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- /* bond_init() must be called after dev_alloc_name() (for the
- * /proc files), but before register_netdevice(), because we
- * need to set function pointers.
- */
- res = bond_init(bond_dev, ¶ms);
- if (res < 0) {
- free_netdev(bond_dev);
- goto out_err;
- }
-
- SET_MODULE_OWNER(bond_dev);
-
- res = register_netdevice(bond_dev);
- if (res < 0) {
- bond_deinit(bond_dev);
- free_netdev(bond_dev);
- goto out_err;
- }
+ sprintf(new_bond_name, "bond%d",i);
+ res = bond_create(new_bond_name,&bonding_defaults, NULL);
+ if (res)
+ goto err;
}
- rtnl_unlock();
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
- return 0;
-
-out_err:
- /*
- * rtnl_unlock() will run netdev_run_todo(), putting the
- * thus-far-registered bonding devices into a state which
- * unregigister_netdevice() will accept
- */
- rtnl_unlock();
+ goto out;
+err:
rtnl_lock();
-
- /* free and unregister all bonds that were successfully added */
bond_free_all();
-
rtnl_unlock();
-
+out:
return res;
+
}
static void __exit bonding_exit(void)
struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
+int bond_create(char *name, struct bond_params *params, struct bonding **newbond);
void bond_deinit(struct net_device *bond_dev);
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev);
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);