daemon: Check if updates are in flight when releasing all IPs
authorMartin Schwenke <martin@meltin.net>
Fri, 24 Jul 2015 05:32:42 +0000 (15:32 +1000)
committerAmitay Isaacs <amitay@gmail.com>
Fri, 31 Jul 2015 03:35:01 +0000 (13:35 +1000)
Some code involved in releasing IPs is not re-entrant.  Memory
corruption can occur if, for example, overlapping attempts are made to
ban a node.  We haven't been able to recreate the corruption but this
should protect against it.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
(Imported from commit 952a50485f68b3cffdf57da84aa9bb9fde630b7e)

server/ctdb_takeover.c

index 29d54f2b175013dfac1677d3f6d0f5d1d2c66977..095ae417103ec8cb870deda90b72adf9b5c7e4aa 100644 (file)
@@ -3246,9 +3246,6 @@ void ctdb_takeover_client_destructor_hook(struct ctdb_client *client)
 }
 
 
-/*
-  release all IPs on shutdown
- */
 void ctdb_release_all_ips(struct ctdb_context *ctdb)
 {
        struct ctdb_vnn *vnn;
@@ -3263,6 +3260,20 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb)
                        continue;
                }
 
+               /* Don't allow multiple releases at once.  Some code,
+                * particularly ctdb_tickle_sentenced_connections() is
+                * not re-entrant */
+               if (vnn->update_in_flight) {
+                       DEBUG(DEBUG_WARNING,
+                             (__location__
+                              " Not releasing IP %s/%u on interface %s, an update is already in progess\n",
+                                   ctdb_addr_to_str(&vnn->public_address),
+                                   vnn->public_netmask_bits,
+                                   ctdb_vnn_iface_string(vnn)));
+                       continue;
+               }
+               vnn->update_in_flight = true;
+
                DEBUG(DEBUG_INFO,("Release of IP %s/%u on interface %s node:-1\n",
                                    ctdb_addr_to_str(&vnn->public_address),
                                    vnn->public_netmask_bits,
@@ -3274,6 +3285,7 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb)
                                  vnn->public_netmask_bits);
                release_kill_clients(ctdb, &vnn->public_address);
                ctdb_vnn_unassign_iface(ctdb, vnn);
+               vnn->update_in_flight = false;
                count++;
        }