From: Andrew Tridgell Date: Sat, 12 May 2007 05:29:06 +0000 (+1000) Subject: more robust freeze/thaw logic X-Git-Tag: tevent-0.9.20~348^2~2750 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f7e3004f0a9e9de8b20c1b50ca10c91d2f4dd4a2;p=thirdparty%2Fsamba.git more robust freeze/thaw logic (This used to be ctdb commit 51c1e51aeb7dfac1683584df7ef1bef98c092f76) --- diff --git a/ctdb/common/ctdb_freeze.c b/ctdb/common/ctdb_freeze.c index b31751d8523..776db55acda 100644 --- a/ctdb/common/ctdb_freeze.c +++ b/ctdb/common/ctdb_freeze.c @@ -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 */ diff --git a/ctdb/common/ctdb_recover.c b/ctdb/common/ctdb_recover.c index 1156a37e789..5a3188c755c 100644 --- a/ctdb/common/ctdb_recover.c +++ b/ctdb/common/ctdb_recover.c @@ -28,6 +28,43 @@ #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, ¶ms); - 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; }