aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_3ad.c10
-rw-r--r--drivers/net/bonding/bond_alb.c58
-rw-r--r--drivers/net/bonding/bond_sysfs.c30
-rw-r--r--drivers/net/bonding/bonding.h14
4 files changed, 78 insertions, 34 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index ea3e64e22e22..187b1b7772ef 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2344,7 +2344,7 @@ int __bond_3ad_get_active_agg_info(struct bonding *bond,
2344 struct slave *slave; 2344 struct slave *slave;
2345 struct port *port; 2345 struct port *port;
2346 2346
2347 bond_for_each_slave(bond, slave, iter) { 2347 bond_for_each_slave_rcu(bond, slave, iter) {
2348 port = &(SLAVE_AD_INFO(slave).port); 2348 port = &(SLAVE_AD_INFO(slave).port);
2349 if (port->aggregator && port->aggregator->is_active) { 2349 if (port->aggregator && port->aggregator->is_active) {
2350 aggregator = port->aggregator; 2350 aggregator = port->aggregator;
@@ -2369,9 +2369,9 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
2369{ 2369{
2370 int ret; 2370 int ret;
2371 2371
2372 read_lock(&bond->lock); 2372 rcu_read_lock();
2373 ret = __bond_3ad_get_active_agg_info(bond, ad_info); 2373 ret = __bond_3ad_get_active_agg_info(bond, ad_info);
2374 read_unlock(&bond->lock); 2374 rcu_read_unlock();
2375 2375
2376 return ret; 2376 return ret;
2377} 2377}
@@ -2388,7 +2388,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
2388 int res = 1; 2388 int res = 1;
2389 int agg_id; 2389 int agg_id;
2390 2390
2391 read_lock(&bond->lock);
2392 if (__bond_3ad_get_active_agg_info(bond, &ad_info)) { 2391 if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
2393 pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n", 2392 pr_debug("%s: Error: __bond_3ad_get_active_agg_info failed\n",
2394 dev->name); 2393 dev->name);
@@ -2406,7 +2405,7 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
2406 slave_agg_no = bond_xmit_hash(bond, skb, slaves_in_agg); 2405 slave_agg_no = bond_xmit_hash(bond, skb, slaves_in_agg);
2407 first_ok_slave = NULL; 2406 first_ok_slave = NULL;
2408 2407
2409 bond_for_each_slave(bond, slave, iter) { 2408 bond_for_each_slave_rcu(bond, slave, iter) {
2410 agg = SLAVE_AD_INFO(slave).port.aggregator; 2409 agg = SLAVE_AD_INFO(slave).port.aggregator;
2411 if (!agg || agg->aggregator_identifier != agg_id) 2410 if (!agg || agg->aggregator_identifier != agg_id)
2412 continue; 2411 continue;
@@ -2436,7 +2435,6 @@ int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
2436 res = bond_dev_queue_xmit(bond, skb, first_ok_slave->dev); 2435 res = bond_dev_queue_xmit(bond, skb, first_ok_slave->dev);
2437 2436
2438out: 2437out:
2439 read_unlock(&bond->lock);
2440 if (res) { 2438 if (res) {
2441 /* no suitable interface, frame not sent */ 2439 /* no suitable interface, frame not sent */
2442 kfree_skb(skb); 2440 kfree_skb(skb);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 576cceae026a..02872405d35d 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -230,7 +230,7 @@ static struct slave *tlb_get_least_loaded_slave(struct bonding *bond)
230 max_gap = LLONG_MIN; 230 max_gap = LLONG_MIN;
231 231
232 /* Find the slave with the largest gap */ 232 /* Find the slave with the largest gap */
233 bond_for_each_slave(bond, slave, iter) { 233 bond_for_each_slave_rcu(bond, slave, iter) {
234 if (SLAVE_IS_OK(slave)) { 234 if (SLAVE_IS_OK(slave)) {
235 long long gap = compute_gap(slave); 235 long long gap = compute_gap(slave);
236 236
@@ -412,6 +412,39 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond)
412 return rx_slave; 412 return rx_slave;
413} 413}
414 414
415/* Caller must hold rcu_read_lock() for read */
416static struct slave *__rlb_next_rx_slave(struct bonding *bond)
417{
418 struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
419 struct slave *before = NULL, *rx_slave = NULL, *slave;
420 struct list_head *iter;
421 bool found = false;
422
423 bond_for_each_slave_rcu(bond, slave, iter) {
424 if (!SLAVE_IS_OK(slave))
425 continue;
426 if (!found) {
427 if (!before || before->speed < slave->speed)
428 before = slave;
429 } else {
430 if (!rx_slave || rx_slave->speed < slave->speed)
431 rx_slave = slave;
432 }
433 if (slave == bond_info->rx_slave)
434 found = true;
435 }
436 /* we didn't find anything after the current or we have something
437 * better before and up to the current slave
438 */
439 if (!rx_slave || (before && rx_slave->speed < before->speed))
440 rx_slave = before;
441
442 if (rx_slave)
443 bond_info->rx_slave = rx_slave;
444
445 return rx_slave;
446}
447
415/* teach the switch the mac of a disabled slave 448/* teach the switch the mac of a disabled slave
416 * on the primary for fault tolerance 449 * on the primary for fault tolerance
417 * 450 *
@@ -628,12 +661,14 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
628{ 661{
629 struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); 662 struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
630 struct arp_pkt *arp = arp_pkt(skb); 663 struct arp_pkt *arp = arp_pkt(skb);
631 struct slave *assigned_slave; 664 struct slave *assigned_slave, *curr_active_slave;
632 struct rlb_client_info *client_info; 665 struct rlb_client_info *client_info;
633 u32 hash_index = 0; 666 u32 hash_index = 0;
634 667
635 _lock_rx_hashtbl(bond); 668 _lock_rx_hashtbl(bond);
636 669
670 curr_active_slave = rcu_dereference(bond->curr_active_slave);
671
637 hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst)); 672 hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
638 client_info = &(bond_info->rx_hashtbl[hash_index]); 673 client_info = &(bond_info->rx_hashtbl[hash_index]);
639 674
@@ -658,14 +693,14 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
658 * that the new client can be assigned to this entry. 693 * that the new client can be assigned to this entry.
659 */ 694 */
660 if (bond->curr_active_slave && 695 if (bond->curr_active_slave &&
661 client_info->slave != bond->curr_active_slave) { 696 client_info->slave != curr_active_slave) {
662 client_info->slave = bond->curr_active_slave; 697 client_info->slave = curr_active_slave;
663 rlb_update_client(client_info); 698 rlb_update_client(client_info);
664 } 699 }
665 } 700 }
666 } 701 }
667 /* assign a new slave */ 702 /* assign a new slave */
668 assigned_slave = rlb_next_rx_slave(bond); 703 assigned_slave = __rlb_next_rx_slave(bond);
669 704
670 if (assigned_slave) { 705 if (assigned_slave) {
671 if (!(client_info->assigned && 706 if (!(client_info->assigned &&
@@ -728,7 +763,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
728 /* Don't modify or load balance ARPs that do not originate locally 763 /* Don't modify or load balance ARPs that do not originate locally
729 * (e.g.,arrive via a bridge). 764 * (e.g.,arrive via a bridge).
730 */ 765 */
731 if (!bond_slave_has_mac(bond, arp->mac_src)) 766 if (!bond_slave_has_mac_rcu(bond, arp->mac_src))
732 return NULL; 767 return NULL;
733 768
734 if (arp->op_code == htons(ARPOP_REPLY)) { 769 if (arp->op_code == htons(ARPOP_REPLY)) {
@@ -1343,11 +1378,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
1343 skb_reset_mac_header(skb); 1378 skb_reset_mac_header(skb);
1344 eth_data = eth_hdr(skb); 1379 eth_data = eth_hdr(skb);
1345 1380
1346 /* make sure that the curr_active_slave do not change during tx
1347 */
1348 read_lock(&bond->lock);
1349 read_lock(&bond->curr_slave_lock);
1350
1351 switch (ntohs(skb->protocol)) { 1381 switch (ntohs(skb->protocol)) {
1352 case ETH_P_IP: { 1382 case ETH_P_IP: {
1353 const struct iphdr *iph = ip_hdr(skb); 1383 const struct iphdr *iph = ip_hdr(skb);
@@ -1429,12 +1459,12 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
1429 1459
1430 if (!tx_slave) { 1460 if (!tx_slave) {
1431 /* unbalanced or unassigned, send through primary */ 1461 /* unbalanced or unassigned, send through primary */
1432 tx_slave = bond->curr_active_slave; 1462 tx_slave = rcu_dereference(bond->curr_active_slave);
1433 bond_info->unbalanced_load += skb->len; 1463 bond_info->unbalanced_load += skb->len;
1434 } 1464 }
1435 1465
1436 if (tx_slave && SLAVE_IS_OK(tx_slave)) { 1466 if (tx_slave && SLAVE_IS_OK(tx_slave)) {
1437 if (tx_slave != bond->curr_active_slave) { 1467 if (tx_slave != rcu_dereference(bond->curr_active_slave)) {
1438 memcpy(eth_data->h_source, 1468 memcpy(eth_data->h_source,
1439 tx_slave->dev->dev_addr, 1469 tx_slave->dev->dev_addr,
1440 ETH_ALEN); 1470 ETH_ALEN);
@@ -1449,8 +1479,6 @@ int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
1449 } 1479 }
1450 } 1480 }
1451 1481
1452 read_unlock(&bond->curr_slave_lock);
1453 read_unlock(&bond->lock);
1454 if (res) { 1482 if (res) {
1455 /* no suitable interface, frame not sent */ 1483 /* no suitable interface, frame not sent */
1456 kfree_skb(skb); 1484 kfree_skb(skb);
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index e9249527e7e7..03bed0ca935e 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -179,7 +179,9 @@ static ssize_t bonding_show_slaves(struct device *d,
179 struct slave *slave; 179 struct slave *slave;
180 int res = 0; 180 int res = 0;
181 181
182 read_lock(&bond->lock); 182 if (!rtnl_trylock())
183 return restart_syscall();
184
183 bond_for_each_slave(bond, slave, iter) { 185 bond_for_each_slave(bond, slave, iter) {
184 if (res > (PAGE_SIZE - IFNAMSIZ)) { 186 if (res > (PAGE_SIZE - IFNAMSIZ)) {
185 /* not enough space for another interface name */ 187 /* not enough space for another interface name */
@@ -190,7 +192,9 @@ static ssize_t bonding_show_slaves(struct device *d,
190 } 192 }
191 res += sprintf(buf + res, "%s ", slave->dev->name); 193 res += sprintf(buf + res, "%s ", slave->dev->name);
192 } 194 }
193 read_unlock(&bond->lock); 195
196 rtnl_unlock();
197
194 if (res) 198 if (res)
195 buf[res-1] = '\n'; /* eat the leftover space */ 199 buf[res-1] = '\n'; /* eat the leftover space */
196 200
@@ -626,6 +630,9 @@ static ssize_t bonding_store_arp_targets(struct device *d,
626 unsigned long *targets_rx; 630 unsigned long *targets_rx;
627 int ind, i, j, ret = -EINVAL; 631 int ind, i, j, ret = -EINVAL;
628 632
633 if (!rtnl_trylock())
634 return restart_syscall();
635
629 targets = bond->params.arp_targets; 636 targets = bond->params.arp_targets;
630 newtarget = in_aton(buf + 1); 637 newtarget = in_aton(buf + 1);
631 /* look for adds */ 638 /* look for adds */
@@ -699,6 +706,7 @@ static ssize_t bonding_store_arp_targets(struct device *d,
699 706
700 ret = count; 707 ret = count;
701out: 708out:
709 rtnl_unlock();
702 return ret; 710 return ret;
703} 711}
704static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets); 712static DEVICE_ATTR(arp_ip_target, S_IRUGO | S_IWUSR , bonding_show_arp_targets, bonding_store_arp_targets);
@@ -1467,7 +1475,6 @@ static ssize_t bonding_show_queue_id(struct device *d,
1467 if (!rtnl_trylock()) 1475 if (!rtnl_trylock())
1468 return restart_syscall(); 1476 return restart_syscall();
1469 1477
1470 read_lock(&bond->lock);
1471 bond_for_each_slave(bond, slave, iter) { 1478 bond_for_each_slave(bond, slave, iter) {
1472 if (res > (PAGE_SIZE - IFNAMSIZ - 6)) { 1479 if (res > (PAGE_SIZE - IFNAMSIZ - 6)) {
1473 /* not enough space for another interface_name:queue_id pair */ 1480 /* not enough space for another interface_name:queue_id pair */
@@ -1479,9 +1486,9 @@ static ssize_t bonding_show_queue_id(struct device *d,
1479 res += sprintf(buf + res, "%s:%d ", 1486 res += sprintf(buf + res, "%s:%d ",
1480 slave->dev->name, slave->queue_id); 1487 slave->dev->name, slave->queue_id);
1481 } 1488 }
1482 read_unlock(&bond->lock);
1483 if (res) 1489 if (res)
1484 buf[res-1] = '\n'; /* eat the leftover space */ 1490 buf[res-1] = '\n'; /* eat the leftover space */
1491
1485 rtnl_unlock(); 1492 rtnl_unlock();
1486 1493
1487 return res; 1494 return res;
@@ -1530,8 +1537,6 @@ static ssize_t bonding_store_queue_id(struct device *d,
1530 if (!sdev) 1537 if (!sdev)
1531 goto err_no_cmd; 1538 goto err_no_cmd;
1532 1539
1533 read_lock(&bond->lock);
1534
1535 /* Search for thes slave and check for duplicate qids */ 1540 /* Search for thes slave and check for duplicate qids */
1536 update_slave = NULL; 1541 update_slave = NULL;
1537 bond_for_each_slave(bond, slave, iter) { 1542 bond_for_each_slave(bond, slave, iter) {
@@ -1542,23 +1547,20 @@ static ssize_t bonding_store_queue_id(struct device *d,
1542 */ 1547 */
1543 update_slave = slave; 1548 update_slave = slave;
1544 else if (qid && qid == slave->queue_id) { 1549 else if (qid && qid == slave->queue_id) {
1545 goto err_no_cmd_unlock; 1550 goto err_no_cmd;
1546 } 1551 }
1547 } 1552 }
1548 1553
1549 if (!update_slave) 1554 if (!update_slave)
1550 goto err_no_cmd_unlock; 1555 goto err_no_cmd;
1551 1556
1552 /* Actually set the qids for the slave */ 1557 /* Actually set the qids for the slave */
1553 update_slave->queue_id = qid; 1558 update_slave->queue_id = qid;
1554 1559
1555 read_unlock(&bond->lock);
1556out: 1560out:
1557 rtnl_unlock(); 1561 rtnl_unlock();
1558 return ret; 1562 return ret;
1559 1563
1560err_no_cmd_unlock:
1561 read_unlock(&bond->lock);
1562err_no_cmd: 1564err_no_cmd:
1563 pr_info("invalid input for queue_id set for %s.\n", 1565 pr_info("invalid input for queue_id set for %s.\n",
1564 bond->dev->name); 1566 bond->dev->name);
@@ -1591,6 +1593,9 @@ static ssize_t bonding_store_slaves_active(struct device *d,
1591 struct list_head *iter; 1593 struct list_head *iter;
1592 struct slave *slave; 1594 struct slave *slave;
1593 1595
1596 if (!rtnl_trylock())
1597 return restart_syscall();
1598
1594 if (sscanf(buf, "%d", &new_value) != 1) { 1599 if (sscanf(buf, "%d", &new_value) != 1) {
1595 pr_err("%s: no all_slaves_active value specified.\n", 1600 pr_err("%s: no all_slaves_active value specified.\n",
1596 bond->dev->name); 1601 bond->dev->name);
@@ -1610,7 +1615,6 @@ static ssize_t bonding_store_slaves_active(struct device *d,
1610 goto out; 1615 goto out;
1611 } 1616 }
1612 1617
1613 read_lock(&bond->lock);
1614 bond_for_each_slave(bond, slave, iter) { 1618 bond_for_each_slave(bond, slave, iter) {
1615 if (!bond_is_active_slave(slave)) { 1619 if (!bond_is_active_slave(slave)) {
1616 if (new_value) 1620 if (new_value)
@@ -1619,8 +1623,8 @@ static ssize_t bonding_store_slaves_active(struct device *d,
1619 slave->inactive = 1; 1623 slave->inactive = 1;
1620 } 1624 }
1621 } 1625 }
1622 read_unlock(&bond->lock);
1623out: 1626out:
1627 rtnl_unlock();
1624 return ret; 1628 return ret;
1625} 1629}
1626static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR, 1630static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 0bd04fbda8e9..bb5c731e2560 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -464,6 +464,20 @@ static inline struct slave *bond_slave_has_mac(struct bonding *bond,
464 return NULL; 464 return NULL;
465} 465}
466 466
467/* Caller must hold rcu_read_lock() for read */
468static inline struct slave *bond_slave_has_mac_rcu(struct bonding *bond,
469 const u8 *mac)
470{
471 struct list_head *iter;
472 struct slave *tmp;
473
474 bond_for_each_slave_rcu(bond, tmp, iter)
475 if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
476 return tmp;
477
478 return NULL;
479}
480
467/* Check if the ip is present in arp ip list, or first free slot if ip == 0 481/* Check if the ip is present in arp ip list, or first free slot if ip == 0
468 * Returns -1 if not found, index if found 482 * Returns -1 if not found, index if found
469 */ 483 */