Import 898b5edfe757cb145960b8f3631029bfd5592119 from ctdb:
[ccan] / ccan / tdb / transaction.c
index 742f188f500dbd4bba8dcbe4f6d080a2663ca7ab..c5580f205d39c074fbbe52f9f5545659638112c3 100644 (file)
@@ -135,6 +135,9 @@ struct tdb_transaction {
        bool prepared;
        tdb_off_t magic_offset;
 
        bool prepared;
        tdb_off_t magic_offset;
 
+       /* set when the GLOBAL_LOCK has been taken */
+       bool global_lock_taken;
+
        /* old file size before transaction */
        tdb_len_t old_map_size;
 
        /* old file size before transaction */
        tdb_len_t old_map_size;
 
@@ -501,6 +504,11 @@ int _tdb_transaction_cancel(struct tdb_context *tdb, int ltype)
                }
        }
 
                }
        }
 
+       if (tdb->transaction->global_lock_taken) {
+               tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 1);
+               tdb->transaction->global_lock_taken = false;
+       }
+
        /* remove any global lock created during the transaction */
        if (tdb->global_lock.count != 0) {
                tdb_brunlock(tdb, tdb->global_lock.ltype,
        /* remove any global lock created during the transaction */
        if (tdb->global_lock.count != 0) {
                tdb_brunlock(tdb, tdb->global_lock.ltype,
@@ -960,11 +968,12 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb)
                return -1;
        }
 
                return -1;
        }
 
+       tdb->transaction->global_lock_taken = true;
+
        if (!(tdb->flags & TDB_NOSYNC)) {
                /* write the recovery data to the end of the file */
                if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n"));
        if (!(tdb->flags & TDB_NOSYNC)) {
                /* write the recovery data to the end of the file */
                if (transaction_setup_recovery(tdb, &tdb->transaction->magic_offset) == -1) {
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: failed to setup recovery data\n"));
-                       tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 1);
                        _tdb_transaction_cancel(tdb, F_WRLCK);
                        return -1;
                }
                        _tdb_transaction_cancel(tdb, F_WRLCK);
                        return -1;
                }
@@ -979,7 +988,6 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb)
                                             tdb->transaction->old_map_size) == -1) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: expansion failed\n"));
                                             tdb->transaction->old_map_size) == -1) {
                        tdb->ecode = TDB_ERR_IO;
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_prepare_commit: expansion failed\n"));
-                       tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 1);
                        _tdb_transaction_cancel(tdb, F_WRLCK);
                        return -1;
                }
                        _tdb_transaction_cancel(tdb, F_WRLCK);
                        return -1;
                }
@@ -1069,7 +1077,6 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                        tdb_transaction_recover(tdb); 
 
                        _tdb_transaction_cancel(tdb, F_WRLCK);
                        tdb_transaction_recover(tdb); 
 
                        _tdb_transaction_cancel(tdb, F_WRLCK);
-                       tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 1);
 
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
                        return -1;
 
                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed\n"));
                        return -1;
@@ -1085,8 +1092,6 @@ int tdb_transaction_commit(struct tdb_context *tdb)
                return -1;
        }
 
                return -1;
        }
 
-       tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 1);
-
        /*
          TODO: maybe write to some dummy hdr field, or write to magic
          offset without mmap, before the last sync, instead of the
        /*
          TODO: maybe write to some dummy hdr field, or write to magic
          offset without mmap, before the last sync, instead of the