ctdb-readonly: Do not abort if revoke of readonly record fails on a node
authorAmitay Isaacs <amitay@gmail.com>
Tue, 12 Aug 2014 13:58:00 +0000 (23:58 +1000)
committerMartin Schwenke <martins@samba.org>
Wed, 13 Aug 2014 09:24:09 +0000 (11:24 +0200)
Revoking readonly record involves first marking the record on dmaster as
RO_REVOKING_READONLY.  Then all the other nodes are sent update_record
control to get rid of RO_DELEGATION.  Once that succeeds, the record
is marked RO_REVOKING_COMPLETE.

Currently, revoking of readonly delegations on the nodes is tried only
once.  If a node goes in recovery, it can fail update_record control and
revoke code will abort ctdb.  Since database recovery would revoke all
readonly delegations anyway, there is no reason to abort.  Simply undo
the start of revoke process by resetting RO_REVOKING_READONLY flag.

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Martin Schwenke <martin@meltin.net>
Autobuild-User(master): Martin Schwenke <martins@samba.org>
Autobuild-Date(master): Wed Aug 13 11:24:09 CEST 2014 on sn-devel-104

ctdb/server/ctdb_call.c

index 7affe44a79545983ff83905532c5473d606b3723..a4fa03d8778e2c05da6b3d28ac067e23cbcd8185 100644 (file)
@@ -1539,7 +1539,6 @@ static void ctdb_revoke_timeout_handler(struct event_context *ev, struct timed_e
 static int ctdb_revoke_all_delegations(struct ctdb_context *ctdb, struct ctdb_db_context *ctdb_db, TDB_DATA tdata, TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA data)
 {
        struct ctdb_revoke_state *state = talloc_zero(ctdb, struct ctdb_revoke_state);
-       int status;
        struct ctdb_ltdb_header new_header;
        TDB_DATA new_data;
 
@@ -1556,12 +1555,6 @@ static int ctdb_revoke_all_delegations(struct ctdb_context *ctdb, struct ctdb_db
                event_loop_once(ctdb->ev);
        }
 
-       status = state->status;
-       if (status != 0) {
-               talloc_free(state);
-               return staus;
-       }
-
        if (ctdb_ltdb_lock(ctdb_db, key) != 0) {
                DEBUG(DEBUG_ERR,("Failed to chainlock the database in revokechild\n"));
                talloc_free(state);
@@ -1586,8 +1579,18 @@ static int ctdb_revoke_all_delegations(struct ctdb_context *ctdb, struct ctdb_db
                talloc_free(state);
                return -1;
        }
-       new_header.rsn++;
-       new_header.flags |= CTDB_REC_RO_REVOKE_COMPLETE;
+
+       /*
+        * If revoke on all nodes succeed, revoke is complete.  Otherwise,
+        * remove CTDB_REC_RO_REVOKING_READONLY flag and retry.
+        */
+       if (state->status == 0) {
+               new_header.rsn++;
+               new_header.flags |= CTDB_REC_RO_REVOKE_COMPLETE;
+       } else {
+               DEBUG(DEBUG_NOTICE, ("Revoke all delegations failed, retrying.\n"));
+               new_header.flags &= ~CTDB_REC_RO_REVOKING_READONLY;
+       }
        if (ctdb_ltdb_store(ctdb_db, key, &new_header, new_data) != 0) {
                ctdb_ltdb_unlock(ctdb_db, key);
                DEBUG(DEBUG_ERR,("Failed to write new record in revokechild\n"));
@@ -1597,7 +1600,7 @@ static int ctdb_revoke_all_delegations(struct ctdb_context *ctdb, struct ctdb_db
        ctdb_ltdb_unlock(ctdb_db, key);
 
        talloc_free(state);
-       return status;
+       return 0;
 }