aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_main.c4
-rw-r--r--drivers/net/bonding/bond_netlink.c9
-rw-r--r--drivers/net/bonding/bond_options.c30
-rw-r--r--drivers/net/bonding/bond_options.h3
-rw-r--r--drivers/net/bonding/bond_sysfs.c24
-rw-r--r--drivers/net/bonding/bonding.h1
6 files changed, 36 insertions, 35 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 59edf18602d9..2ca949f6e995 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3123,6 +3123,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
3123 struct ifslave k_sinfo; 3123 struct ifslave k_sinfo;
3124 struct ifslave __user *u_sinfo = NULL; 3124 struct ifslave __user *u_sinfo = NULL;
3125 struct mii_ioctl_data *mii = NULL; 3125 struct mii_ioctl_data *mii = NULL;
3126 struct bond_opt_value newval;
3126 struct net *net; 3127 struct net *net;
3127 int res = 0; 3128 int res = 0;
3128 3129
@@ -3218,7 +3219,8 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
3218 break; 3219 break;
3219 case BOND_CHANGE_ACTIVE_OLD: 3220 case BOND_CHANGE_ACTIVE_OLD:
3220 case SIOCBONDCHANGEACTIVE: 3221 case SIOCBONDCHANGEACTIVE:
3221 res = bond_option_active_slave_set(bond, slave_dev); 3222 bond_opt_initstr(&newval, slave_dev->name);
3223 res = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
3222 break; 3224 break;
3223 default: 3225 default:
3224 res = -EOPNOTSUPP; 3226 res = -EOPNOTSUPP;
diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c
index 2175e1926e5a..dba1f2e22371 100644
--- a/drivers/net/bonding/bond_netlink.c
+++ b/drivers/net/bonding/bond_netlink.c
@@ -116,16 +116,17 @@ static int bond_changelink(struct net_device *bond_dev,
116 if (data[IFLA_BOND_ACTIVE_SLAVE]) { 116 if (data[IFLA_BOND_ACTIVE_SLAVE]) {
117 int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]); 117 int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
118 struct net_device *slave_dev; 118 struct net_device *slave_dev;
119 char *active_slave = "";
119 120
120 if (ifindex == 0) { 121 if (ifindex != 0) {
121 slave_dev = NULL;
122 } else {
123 slave_dev = __dev_get_by_index(dev_net(bond_dev), 122 slave_dev = __dev_get_by_index(dev_net(bond_dev),
124 ifindex); 123 ifindex);
125 if (!slave_dev) 124 if (!slave_dev)
126 return -ENODEV; 125 return -ENODEV;
126 active_slave = slave_dev->name;
127 } 127 }
128 err = bond_option_active_slave_set(bond, slave_dev); 128 bond_opt_initstr(&newval, active_slave);
129 err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
129 if (err) 130 if (err)
130 return err; 131 return err;
131 } 132 }
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 18b1cc0d8b80..2315104de8c0 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -244,6 +244,16 @@ static struct bond_option bond_opts[] = {
244 .values = bond_use_carrier_tbl, 244 .values = bond_use_carrier_tbl,
245 .set = bond_option_use_carrier_set 245 .set = bond_option_use_carrier_set
246 }, 246 },
247 [BOND_OPT_ACTIVE_SLAVE] = {
248 .id = BOND_OPT_ACTIVE_SLAVE,
249 .name = "active_slave",
250 .desc = "Currently active slave",
251 .flags = BOND_OPTFLAG_RAWVAL,
252 .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
253 BIT(BOND_MODE_TLB) |
254 BIT(BOND_MODE_ALB)),
255 .set = bond_option_active_slave_set
256 },
247 { } 257 { }
248}; 258};
249 259
@@ -556,10 +566,21 @@ struct net_device *bond_option_active_slave_get(struct bonding *bond)
556} 566}
557 567
558int bond_option_active_slave_set(struct bonding *bond, 568int bond_option_active_slave_set(struct bonding *bond,
559 struct net_device *slave_dev) 569 struct bond_opt_value *newval)
560{ 570{
571 char ifname[IFNAMSIZ] = { 0, };
572 struct net_device *slave_dev;
561 int ret = 0; 573 int ret = 0;
562 574
575 sscanf(newval->string, "%15s", ifname); /* IFNAMSIZ */
576 if (!strlen(ifname) || newval->string[0] == '\n') {
577 slave_dev = NULL;
578 } else {
579 slave_dev = __dev_get_by_name(dev_net(bond->dev), ifname);
580 if (!slave_dev)
581 return -ENODEV;
582 }
583
563 if (slave_dev) { 584 if (slave_dev) {
564 if (!netif_is_bond_slave(slave_dev)) { 585 if (!netif_is_bond_slave(slave_dev)) {
565 pr_err("Device %s is not bonding slave.\n", 586 pr_err("Device %s is not bonding slave.\n",
@@ -574,12 +595,6 @@ int bond_option_active_slave_set(struct bonding *bond,
574 } 595 }
575 } 596 }
576 597
577 if (!USES_PRIMARY(bond->params.mode)) {
578 pr_err("%s: Unable to change active slave; %s is in mode %d\n",
579 bond->dev->name, bond->dev->name, bond->params.mode);
580 return -EINVAL;
581 }
582
583 block_netpoll_tx(); 598 block_netpoll_tx();
584 write_lock_bh(&bond->curr_slave_lock); 599 write_lock_bh(&bond->curr_slave_lock);
585 600
@@ -616,6 +631,7 @@ int bond_option_active_slave_set(struct bonding *bond,
616 631
617 write_unlock_bh(&bond->curr_slave_lock); 632 write_unlock_bh(&bond->curr_slave_lock);
618 unblock_netpoll_tx(); 633 unblock_netpoll_tx();
634
619 return ret; 635 return ret;
620} 636}
621 637
diff --git a/drivers/net/bonding/bond_options.h b/drivers/net/bonding/bond_options.h
index 229f5c15a1a4..1f486a7d1e14 100644
--- a/drivers/net/bonding/bond_options.h
+++ b/drivers/net/bonding/bond_options.h
@@ -56,6 +56,7 @@ enum {
56 BOND_OPT_PRIMARY, 56 BOND_OPT_PRIMARY,
57 BOND_OPT_PRIMARY_RESELECT, 57 BOND_OPT_PRIMARY_RESELECT,
58 BOND_OPT_USE_CARRIER, 58 BOND_OPT_USE_CARRIER,
59 BOND_OPT_ACTIVE_SLAVE,
59 BOND_OPT_LAST 60 BOND_OPT_LAST
60}; 61};
61 62
@@ -150,4 +151,6 @@ int bond_option_primary_reselect_set(struct bonding *bond,
150 struct bond_opt_value *newval); 151 struct bond_opt_value *newval);
151int bond_option_use_carrier_set(struct bonding *bond, 152int bond_option_use_carrier_set(struct bonding *bond,
152 struct bond_opt_value *newval); 153 struct bond_opt_value *newval);
154int bond_option_active_slave_set(struct bonding *bond,
155 struct bond_opt_value *newval);
153#endif /* _BOND_OPTIONS_H */ 156#endif /* _BOND_OPTIONS_H */
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 004048240def..181a59d7241e 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -809,34 +809,14 @@ static ssize_t bonding_store_active_slave(struct device *d,
809 struct device_attribute *attr, 809 struct device_attribute *attr,
810 const char *buf, size_t count) 810 const char *buf, size_t count)
811{ 811{
812 int ret;
813 struct bonding *bond = to_bond(d); 812 struct bonding *bond = to_bond(d);
814 char ifname[IFNAMSIZ]; 813 int ret;
815 struct net_device *dev;
816
817 if (!rtnl_trylock())
818 return restart_syscall();
819
820 sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
821 if (!strlen(ifname) || buf[0] == '\n') {
822 dev = NULL;
823 } else {
824 dev = __dev_get_by_name(dev_net(bond->dev), ifname);
825 if (!dev) {
826 ret = -ENODEV;
827 goto out;
828 }
829 }
830 814
831 ret = bond_option_active_slave_set(bond, dev); 815 ret = bond_opt_tryset_rtnl(bond, BOND_OPT_ACTIVE_SLAVE, (char *)buf);
832 if (!ret) 816 if (!ret)
833 ret = count; 817 ret = count;
834 818
835 out:
836 rtnl_unlock();
837
838 return ret; 819 return ret;
839
840} 820}
841static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR, 821static DEVICE_ATTR(active_slave, S_IRUGO | S_IWUSR,
842 bonding_show_active_slave, bonding_store_active_slave); 822 bonding_show_active_slave, bonding_store_active_slave);
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 51f3b0ad11ab..4ac79e1dd78f 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -452,7 +452,6 @@ void bond_setup(struct net_device *bond_dev);
452unsigned int bond_get_num_tx_queues(void); 452unsigned int bond_get_num_tx_queues(void);
453int bond_netlink_init(void); 453int bond_netlink_init(void);
454void bond_netlink_fini(void); 454void bond_netlink_fini(void);
455int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev);
456int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target); 455int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
457int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target); 456int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
458int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp); 457int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp);