Dont allow client processes to attach to databases while we are still in recovery...
[sahlberg/ctdb.git] / server / ctdb_ltdb_server.c
index 47a2d6a693c2d2c488391a86ecdf53cc80bee1a1..8340c37fbdef9ed0bd693d0b38ce859a3d7d0c87 100644 (file)
@@ -18,7 +18,7 @@
 */
 
 #include "includes.h"
-#include "lib/events/events.h"
+#include "lib/tevent/tevent.h"
 #include "lib/tdb/include/tdb.h"
 #include "system/network.h"
 #include "system/filesys.h"
@@ -141,7 +141,6 @@ int ctdb_ltdb_lock_requeue(struct ctdb_db_context *ctdb_db,
        /* now the contended path */
        h = ctdb_lockwait(ctdb_db, key, lock_fetch_callback, state);
        if (h == NULL) {
-               tdb_chainunlock(tdb, key);
                return -1;
        }
 
@@ -170,7 +169,11 @@ int ctdb_ltdb_lock_fetch_requeue(struct ctdb_db_context *ctdb_db,
        if (ret == 0) {
                ret = ctdb_ltdb_fetch(ctdb_db, key, header, hdr, data);
                if (ret != 0) {
-                       ctdb_ltdb_unlock(ctdb_db, key);
+                       int uret;
+                       uret = ctdb_ltdb_unlock(ctdb_db, key);
+                       if (uret != 0) {
+                               DEBUG(DEBUG_ERR,(__location__ " ctdb_ltdb_unlock() failed with error %d\n", uret));
+                       }
                }
        }
        return ret;
@@ -510,7 +513,8 @@ int32_t ctdb_control_db_get_health(struct ctdb_context *ctdb,
   return 0 on success, -1 on failure
  */
 static int ctdb_local_attach(struct ctdb_context *ctdb, const char *db_name,
-                            bool persistent, const char *unhealthy_reason)
+                            bool persistent, const char *unhealthy_reason,
+                            bool jenkinshash)
 {
        struct ctdb_db_context *ctdb_db, *tmp_db;
        int ret;
@@ -589,10 +593,13 @@ static int ctdb_local_attach(struct ctdb_context *ctdb, const char *db_name,
                                           db_name, ctdb->pnn);
 
        tdb_flags = persistent? TDB_DEFAULT : TDB_CLEAR_IF_FIRST | TDB_NOSYNC;
-       if (!ctdb->do_setsched) {
+       if (ctdb->valgrinding) {
                tdb_flags |= TDB_NOMMAP;
        }
        tdb_flags |= TDB_DISALLOW_NESTING;
+       if (jenkinshash) {
+               tdb_flags |= TDB_INCOMPATIBLE_HASH;
+       }
 
 again:
        ctdb_db->ltdb = tdb_wrap_open(ctdb, ctdb_db->db_path, 
@@ -743,17 +750,33 @@ again:
  */
 int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
                               TDB_DATA *outdata, uint64_t tdb_flags, 
-                              bool persistent)
+                              bool persistent, uint32_t client_id)
 {
        const char *db_name = (const char *)indata.dptr;
        struct ctdb_db_context *db;
-       struct ctdb_node *node = ctdb->nodes[ctdb->pnn];
+       struct ctdb_node *node;
+
+       /* dont allow any local clients to attach while we are in recovery mode
+        * except for the recovery daemon.
+        * allow all attach from the network since these are always from remote
+        * recovery daemons.
+        */
+       if (ctdb->recovery_mode == CTDB_RECOVERY_ACTIVE && client_id != 0) {
+               struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
+
+               if (client != NULL && client->pid != ctdb->recoverd_pid) {
+                       DEBUG(DEBUG_ERR,("DB Attach to database %s refused for client with pid:%d since node is in recovery mode.\n", db_name, client->pid));
+                       return -1;
+               }
+       }
+
+       node = ctdb->nodes[ctdb->pnn];
 
        /* the client can optionally pass additional tdb flags, but we
           only allow a subset of those on the database in ctdb. Note
           that tdb_flags is passed in via the (otherwise unused)
           srvid to the attach control */
-       tdb_flags &= TDB_NOSYNC;
+       tdb_flags &= (TDB_NOSYNC|TDB_INCOMPATIBLE_HASH);
 
        /* If the node is inactive it is not part of the cluster
           and we should not allow clients to attach to any
@@ -774,7 +797,7 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
                return 0;
        }
 
-       if (ctdb_local_attach(ctdb, db_name, persistent, NULL) != 0) {
+       if (ctdb_local_attach(ctdb, db_name, persistent, NULL, (tdb_flags&TDB_INCOMPATIBLE_HASH)?true:false) != 0) {
                return -1;
        }
 
@@ -790,8 +813,11 @@ int32_t ctdb_control_db_attach(struct ctdb_context *ctdb, TDB_DATA indata,
        outdata->dptr  = (uint8_t *)&db->db_id;
        outdata->dsize = sizeof(db->db_id);
 
+       /* Try to ensure it's locked in mem */
+       ctdb_lockdown_memory(ctdb);
+
        /* tell all the other nodes about this database */
-       ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_ALL, 0,
+       ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_ALL, tdb_flags,
                                 persistent?CTDB_CONTROL_DB_ATTACH_PERSISTENT:
                                                CTDB_CONTROL_DB_ATTACH,
                                 0, CTDB_CTRL_FLAG_NOREPLY,
@@ -847,7 +873,7 @@ static int ctdb_attach_persistent(struct ctdb_context *ctdb,
                }
                p[4] = 0;
 
-               if (ctdb_local_attach(ctdb, s, true, unhealthy_reason) != 0) {
+               if (ctdb_local_attach(ctdb, s, true, unhealthy_reason, 0) != 0) {
                        DEBUG(DEBUG_ERR,("Failed to attach to persistent database '%s'\n", de->d_name));
                        closedir(d);
                        talloc_free(s);