]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: active bonding - ports may not failback if all ports go down
authorMukesh Kacker <mukesh.kacker@oracle.com>
Sat, 31 May 2014 00:44:16 +0000 (17:44 -0700)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Wed, 8 Jul 2015 21:00:00 +0000 (14:00 -0700)
When active bonding is enabled, ports failover and failback if
ports are enabled/disabled. If ALL ports go down, then no
failover happens since there is no available port to failover to.
In that case, some ports not hosting any migrated interfaces are
not resurrected.

Fix resurrects ports when they dont have an IP address set and
are failing back and RDS active bonding has state on them. Some,
debug/log messages are also improved such as to indicated when
a failover fails to happen.

Orabug: 18875563

Signed-off-by: Mukesh Kacker <mukesh.kacker@oracle.com>
Signed-off-by: Chien-Hua Yen <chien.yen@oracle.com>
(cherry picked from commit 65e125ed4457a25bebe9d69c267a3ce06bf75961)

net/rds/ib.c

index 187f2c90916144d9ae1507209d4427eede5a3199..9eb6621595b938a35ad713622187e3701c2d1a46 100644 (file)
@@ -705,9 +705,18 @@ static int rds_ib_move_ip(char                     *from_dev,
                        "from %s to %s\n",
                        NIPQUAD(addr), from_dev2, to_dev2);
        } else {
-               printk(KERN_NOTICE
-                       "RDS/IB: IP %u.%u.%u.%u migrated from %s to %s\n",
-                               NIPQUAD(addr), from_dev2, to_dev2);
+               if (strcmp(from_dev2, to_dev2) == 0) {
+                       /* from_dev2, to_dev2 are identical */
+                       printk(KERN_NOTICE
+                              "RDS/IB: IP %u.%u.%u.%u resurrected on migrated "
+                              "interface %s\n",
+                              NIPQUAD(addr), to_dev2);
+               } else {
+                       /* from_dev2, to_dev2 are different! */
+                       printk(KERN_NOTICE
+                              "RDS/IB: IP %u.%u.%u.%u migrated from %s to %s\n",
+                              NIPQUAD(addr), from_dev2, to_dev2);
+               }
 
                rds_ibdev = ip_config[from_port].rds_ibdev;
                if (!rds_ibdev)
@@ -885,23 +894,134 @@ static void rds_ib_set_port(struct rds_ib_device *rds_ibdev,
        }
 }
 
+static int rds_ib_testset_ip(u8 port)
+{
+       struct ifreq            *ir;
+       struct sockaddr_in      *sin;
+       struct page             *page;
+       int                     ret = 0;
+       int                     ii;
+
+       if (!ip_config[port].ip_addr) {
+               printk(KERN_WARNING "RDS/IB: no port %u IP available!\n",
+                      port);
+               return 0;
+       }
+
+       page = alloc_page(GFP_HIGHUSER);
+       if (!page) {
+               printk(KERN_ERR "RDS/IB: alloc_page failed .. NO MEM\n");
+               return 1;
+       }
+
+       ir = (struct ifreq *)kmap(page);
+       memset(ir, 0, sizeof(struct ifreq));
+       sin = (struct sockaddr_in *)&ir->ifr_addr;
+       sin->sin_family = AF_INET;
+
+
+       /*
+        * If the primary IP is not set revive it
+        * and also the IP addrs on aliases
+        */
+
+       strcpy(ir->ifr_ifrn.ifrn_name, ip_config[port].dev->name);
+       ret = inet_ioctl(rds_ib_inet_socket, SIOCGIFADDR,
+                        (unsigned long) ir);
+       if (ret == -EADDRNOTAVAIL) {
+               /* Set the IP on this port */
+               ret = rds_ib_set_ip(ip_config[port].dev,
+                                   ip_config[port].dev->dev_addr,
+                                   ip_config[port].dev->name,
+                                   ip_config[port].ip_addr,
+                                   ip_config[port].ip_bcast,
+                                   ip_config[port].ip_mask);
+               if (ret) {
+                       printk(KERN_ERR "RDS/IP: failed to resurrect "
+                              "IP %u.%u.%u.%u on %s failed (%d)\n",
+                              NIPQUAD(ip_config[port].ip_addr),
+                              ip_config[port].dev->name, ret);
+                       goto out;
+               }
+               printk(KERN_NOTICE
+                      "RDS/IB: IP %u.%u.%u.%u resurrected on interface %s\n",
+                      NIPQUAD(ip_config[port].ip_addr),
+                      ip_config[port].dev->name);
+               for (ii = 0; ii < ip_config[port].alias_cnt; ii++) {
+                       ret = rds_ib_set_ip(ip_config[port].dev,
+                                       ip_config[port].dev->dev_addr,
+                                       ip_config[port].aliases[ii].if_name,
+                                       ip_config[port].aliases[ii].ip_addr,
+                                       ip_config[port].aliases[ii].ip_bcast,
+                                       ip_config[port].aliases[ii].ip_mask);
+                       if (ret) {
+                               printk(KERN_ERR "RDS/IP: failed to resurrect "
+                                      "IP %u.%u.%u.%u "
+                                      "on alias %s failed (%d)\n",
+                                      NIPQUAD(ip_config[port].
+                                              aliases[ii].ip_addr),
+                                      ip_config[port].aliases[ii].if_name,
+                                      ret);
+                               goto out;
+                       }
+                       printk(KERN_NOTICE
+                              "RDS/IB: IP %u.%u.%u.%u resurrected"
+                              " on alias %s on interface %s\n",
+                              NIPQUAD(ip_config[port].ip_addr),
+                              ip_config[port].aliases[ii].if_name,
+                              ip_config[port].dev->name);
+               }
+       } else if (ret) {
+               printk(KERN_ERR "RDS/IB: inet_ioctl(SIOCGIFADDR) "
+                      "failed (%d)\n", ret);
+       } else {
+               rdsdebug("Primary addr already set on port %u, "
+                        "devname %s\n",
+                        port, ip_config[port].dev->name);
+       }
+out:
+       kunmap(page);
+       __free_page(page);
+
+       return ret;
+}
+
+
 static void rds_ib_do_failover(u8 from_port, u8 to_port, u8 arp_port,
                                int event_type)
 {
        u8      j;
        int     ret;
 
+       if (!from_port) {
+               printk(KERN_ERR "RDS/IP: port failover request from invalid port!\n");
+               return;
+       }
+
        if (!ip_config[from_port].ip_addr)
                return;
 
-       if (!to_port)
+       if (!to_port) {
+               /* get a port to failover to */
                to_port = rds_ib_get_failover_port(from_port);
 
+               if (!to_port) {
+                       /* we tried, but did not get a failover port! */
+                       rdsdebug("RDS/IP: IP %u.%u.%u.%u failed to "
+                               "migrate from %s: no destination port "
+                               "available!\n",
+                                NIPQUAD(ip_config[from_port].ip_addr),
+                                ip_config[from_port].if_name);
+                       return;
+               }
+       }
+
        if (!arp_port)
                arp_port = to_port;
 
-       if (to_port) {
-               if (!rds_ib_move_ip(
+       BUG_ON(!to_port);
+
+       if (!rds_ib_move_ip(
                        ip_config[from_port].if_name,
                        ip_config[to_port].if_name,
                        from_port,
@@ -914,27 +1034,25 @@ static void rds_ib_do_failover(u8 from_port, u8 to_port, u8 arp_port,
                        0,
                        1)) {
 
-                       ip_config[from_port].ip_active_port = to_port;
-                       for (j = 0; j < ip_config[from_port].
-                               alias_cnt; j++) {
+               ip_config[from_port].ip_active_port = to_port;
+               for (j = 0; j < ip_config[from_port].
+                            alias_cnt; j++) {
 
-                               ret = rds_ib_move_ip(
-                                       ip_config[from_port].
-                                               aliases[j].if_name,
+                       ret = rds_ib_move_ip(
+                                       ip_config[from_port].aliases[j].if_name,
                                        ip_config[to_port].if_name,
                                        from_port,
                                        to_port,
                                        arp_port,
                                        ip_config[from_port].
-                                               aliases[j].ip_addr,
+                                       aliases[j].ip_addr,
                                        ip_config[from_port].
-                                               aliases[j].ip_bcast,
+                                       aliases[j].ip_bcast,
                                        ip_config[from_port].
-                                               aliases[j].ip_mask,
+                                       aliases[j].ip_mask,
                                        event_type,
                                        1,
                                        1);
-                       }
                }
        }
 }
@@ -985,6 +1103,29 @@ static void rds_ib_do_failback(u8 port, int event_type)
                                        0);
                        }
                }
+       } else {
+               /*
+                * Our 'active_port' is parked at its home base so 'failback'
+                * is just an interface coming UP.
+                *
+                * We get here in two cases.
+                * (1) When a startup script (such as during boot) brings up
+                *     the interface the IP address is set by it and we dont
+                *     do anything here!
+                * (2) When this port went DOWN, it tried but did not succeed
+                *     in failing over(no UP ports left to failover to!)
+                *     so the 'failover' failed and our 'active port' stayed
+                *     parked at its original place.
+                *     If such as port is being resurrected, it will not have
+                *     an IP address set we resurrect it here!
+                */
+               /* Test IP addresses and set them if not already set */
+               ret = rds_ib_testset_ip(port);
+               if (ret) {
+                       rdsdebug("RDS/IP: failed to ressurrect "
+                                "port %u devname %s or one if its aliases\n",
+                                port, ip_config[port].dev->name);
+               }
        }
 }