]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
more robust freeze/thaw logic
authorAndrew Tridgell <tridge@samba.org>
Sat, 12 May 2007 05:29:06 +0000 (15:29 +1000)
committerAndrew Tridgell <tridge@samba.org>
Sat, 12 May 2007 05:29:06 +0000 (15:29 +1000)
(This used to be ctdb commit 51c1e51aeb7dfac1683584df7ef1bef98c092f76)

ctdb/common/ctdb_freeze.c
ctdb/common/ctdb_recover.c

index b31751d85239b8707cb6724c78cf82469f7fa6d3..776db55acdacae9b3f2c2c4a38e5d4b5556e615e 100644 (file)
@@ -42,34 +42,6 @@ static int ctdb_lock_all_databases(struct ctdb_context *ctdb)
        return 0;
 }
 
-/*
-  lock all databases - mark only
- */
-static int ctdb_lock_all_databases_mark(struct ctdb_context *ctdb)
-{
-       struct ctdb_db_context *ctdb_db;
-       for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
-               if (tdb_lockall_mark(ctdb_db->ltdb->tdb) != 0) {
-                       return -1;
-               }
-       }
-       return 0;
-}
-
-/*
-  lock all databases - unmark only
- */
-static int ctdb_lock_all_databases_unmark(struct ctdb_context *ctdb)
-{
-       struct ctdb_db_context *ctdb_db;
-       for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
-               if (tdb_lockall_unmark(ctdb_db->ltdb->tdb) != 0) {
-                       return -1;
-               }
-       }
-       return 0;
-}
-
 /*
   a list of control requests waiting for a freeze lock child to get
   the database locks
@@ -94,9 +66,6 @@ struct ctdb_freeze_handle {
  */    
 static int ctdb_freeze_handle_destructor(struct ctdb_freeze_handle *h)
 {
-       if (h->ctdb->freeze_mode == CTDB_FREEZE_FROZEN) {
-               ctdb_lock_all_databases_unmark(h->ctdb);
-       }
        h->ctdb->freeze_mode = CTDB_FREEZE_NONE;
        kill(h->child, SIGKILL);
        waitpid(h->child, NULL, 0);
@@ -112,7 +81,6 @@ static void ctdb_freeze_lock_handler(struct event_context *ev, struct fd_event *
        struct ctdb_freeze_handle *h = talloc_get_type(private_data, struct ctdb_freeze_handle);
        int32_t status;
        struct ctdb_freeze_waiter *w;
-       int ret;
 
        if (read(h->fd, &status, sizeof(status)) != sizeof(status)) {
                DEBUG(0,("read error from freeze lock child\n"));
@@ -126,13 +94,6 @@ static void ctdb_freeze_lock_handler(struct event_context *ev, struct fd_event *
                return;
        }
 
-       ret = ctdb_lock_all_databases_mark(h->ctdb);
-       if (ret == -1) {
-               DEBUG(0,("Failed to mark locks in ctdb_freeze\n"));
-               talloc_free(h);
-               return;
-       }
-
        h->ctdb->freeze_mode = CTDB_FREEZE_FROZEN;
 
        /* notify the waiters */
index 1156a37e78922652792e40e97f92ae81802c0122..5a3188c755c6f09a81758c053bd25ebba7dee0f3 100644 (file)
 #include "lib/util/dlinklist.h"
 #include "db_wrap.h"
 
+/*
+  lock all databases - mark only
+ */
+static int ctdb_lock_all_databases_mark(struct ctdb_context *ctdb)
+{
+       struct ctdb_db_context *ctdb_db;
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("Attempt to mark all databases locked when not frozen\n"));
+               return -1;
+       }
+       for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
+               if (tdb_lockall_mark(ctdb_db->ltdb->tdb) != 0) {
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+/*
+  lock all databases - unmark only
+ */
+static int ctdb_lock_all_databases_unmark(struct ctdb_context *ctdb)
+{
+       struct ctdb_db_context *ctdb_db;
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("Attempt to unmark all databases locked when not frozen\n"));
+               return -1;
+       }
+       for (ctdb_db=ctdb->db_list;ctdb_db;ctdb_db=ctdb_db->next) {
+               if (tdb_lockall_unmark(ctdb_db->ltdb->tdb) != 0) {
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+
 int 
 ctdb_control_getvnnmap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA indata, TDB_DATA *outdata)
 {
@@ -173,6 +210,11 @@ int32_t ctdb_control_pull_db(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DAT
        int i;
        size_t len = 0;
 
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("rejecting ctdb_control_pull_db when not frozen\n"));
+               return -1;
+       }
+
        pull = (struct ctdb_control_pulldb *)indata.dptr;
        
        ctdb_db = find_ctdb_db(ctdb, pull->db_id);
@@ -187,14 +229,14 @@ int32_t ctdb_control_pull_db(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DAT
        params.recs = talloc_array(outdata, struct getkeys_rec, 0);
        CTDB_NO_MEMORY(ctdb, params.recs);
 
-       if (tdb_lockall_nonblock(ctdb_db->ltdb->tdb) != 0) {
-               DEBUG(0,(__location__ " Failed to get nonblock lock on entired db - failing\n"));
+       if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+               DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
                return -1;
        }
 
        tdb_traverse_read(ctdb_db->ltdb->tdb, traverse_getkeys, &params);
 
-       tdb_unlockall(ctdb_db->ltdb->tdb);
+       ctdb_lock_all_databases_unmark(ctdb);
 
        reply = talloc(outdata, struct ctdb_control_pulldb_reply);
        CTDB_NO_MEMORY(ctdb, reply);
@@ -231,6 +273,11 @@ int32_t ctdb_control_push_db(struct ctdb_context *ctdb, TDB_DATA indata)
        int i, ret;
        struct ctdb_rec_data *rec;
 
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("rejecting ctdb_control_push_db when not frozen\n"));
+               return -1;
+       }
+
        if (indata.dsize < offsetof(struct ctdb_control_pulldb_reply, data)) {
                DEBUG(0,(__location__ " invalid data in pulldb reply\n"));
                return -1;
@@ -242,8 +289,8 @@ int32_t ctdb_control_push_db(struct ctdb_context *ctdb, TDB_DATA indata)
                return -1;
        }
 
-       if (tdb_lockall_nonblock(ctdb_db->ltdb->tdb) != 0) {
-               DEBUG(0,(__location__ " Failed to get nonblock lock on entired db - failing\n"));
+       if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+               DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
                return -1;
        }
 
@@ -260,8 +307,7 @@ int32_t ctdb_control_push_db(struct ctdb_context *ctdb, TDB_DATA indata)
 
                if (data.dsize < sizeof(struct ctdb_ltdb_header)) {
                        DEBUG(0,(__location__ " bad ltdb record\n"));
-                       ctdb_ltdb_unlock(ctdb_db, key);
-                       return -1;
+                       goto failed;
                }
                hdr = (struct ctdb_ltdb_header *)data.dptr;
                data.dptr += sizeof(*hdr);
@@ -270,24 +316,25 @@ int32_t ctdb_control_push_db(struct ctdb_context *ctdb, TDB_DATA indata)
                ret = ctdb_ltdb_fetch(ctdb_db, key, &header, NULL, NULL);
                if (ret != 0) {
                        DEBUG(0, (__location__ " Unable to fetch record\n"));
-                       tdb_unlockall(ctdb_db->ltdb->tdb);
-                       return -1;
+                       goto failed;
                }
                if (header.rsn < hdr->rsn) {
                        ret = ctdb_ltdb_store(ctdb_db, key, hdr, data);
                        if (ret != 0) {
                                DEBUG(0, (__location__ " Unable to store record\n"));
-                               tdb_unlockall(ctdb_db->ltdb->tdb);
-                               return -1;
+                               goto failed;
                        }
                }
 
                rec = (struct ctdb_rec_data *)(rec->length + (uint8_t *)rec);
        }           
 
-       tdb_unlockall(ctdb_db->ltdb->tdb);
-
+       ctdb_lock_all_databases_unmark(ctdb);
        return 0;
+
+failed:
+       ctdb_lock_all_databases_unmark(ctdb);
+       return -1;
 }
 
 
@@ -312,20 +359,25 @@ int32_t ctdb_control_set_dmaster(struct ctdb_context *ctdb, TDB_DATA indata)
        struct ctdb_control_set_dmaster *p = (struct ctdb_control_set_dmaster *)indata.dptr;
        struct ctdb_db_context *ctdb_db;
 
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("rejecting ctdb_control_set_dmaster when not frozen\n"));
+               return -1;
+       }
+
        ctdb_db = find_ctdb_db(ctdb, p->db_id);
        if (!ctdb_db) {
                DEBUG(0,(__location__ " Unknown db 0x%08x\n", p->db_id));
                return -1;
        }
 
-       if (tdb_lockall_nonblock(ctdb_db->ltdb->tdb) != 0) {
-               DEBUG(0,(__location__ " Failed to get nonblock lock on entired db - failing\n"));
+       if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+               DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
                return -1;
-       }       
+       }
 
        tdb_traverse(ctdb_db->ltdb->tdb, traverse_setdmaster, &p->dmaster);
 
-       tdb_unlockall(ctdb_db->ltdb->tdb);
+       ctdb_lock_all_databases_unmark(ctdb);
        
        return 0;
 }
@@ -335,7 +387,6 @@ static int traverse_cleardb(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data
 {
        int ret;
 
-
        ret = tdb_delete(tdb, key);
        if (ret) {
                DEBUG(0,(__location__ " failed to delete tdb record\n"));
@@ -350,20 +401,25 @@ int32_t ctdb_control_clear_db(struct ctdb_context *ctdb, TDB_DATA indata)
        uint32_t dbid = *(uint32_t *)indata.dptr;
        struct ctdb_db_context *ctdb_db;
 
+       if (ctdb->freeze_mode != CTDB_FREEZE_FROZEN) {
+               DEBUG(0,("rejecting ctdb_control_clear_db when not frozen\n"));
+               return -1;
+       }
+
        ctdb_db = find_ctdb_db(ctdb, dbid);
        if (!ctdb_db) {
                DEBUG(0,(__location__ " Unknown db 0x%08x\n",dbid));
                return -1;
        }
 
-       if (tdb_lockall_nonblock(ctdb_db->ltdb->tdb) != 0) {
-               DEBUG(0,(__location__ " Failed to get nonblock lock on entired db - failing\n"));
+       if (ctdb_lock_all_databases_mark(ctdb) != 0) {
+               DEBUG(0,(__location__ " Failed to get lock on entired db - failing\n"));
                return -1;
-       }       
+       }
 
        tdb_traverse(ctdb_db->ltdb->tdb, traverse_cleardb, NULL);
 
-       tdb_unlockall(ctdb_db->ltdb->tdb);
+       ctdb_lock_all_databases_unmark(ctdb);
 
        return 0;
 }