X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ftdb%2Ftransaction.c;h=261428fd9c9e5d0b902266ff3b91f9a24a37b898;hb=f7b3eb1ecf6935dbf2b6c283e848ebfbaaeca47c;hp=742f188f500dbd4bba8dcbe4f6d080a2663ca7ab;hpb=4364f6a8e21a8f7c561f121af3a834cf7e0649ce;p=ccan diff --git a/ccan/tdb/transaction.c b/ccan/tdb/transaction.c index 742f188f..261428fd 100644 --- a/ccan/tdb/transaction.c +++ b/ccan/tdb/transaction.c @@ -135,6 +135,9 @@ struct tdb_transaction { 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; @@ -491,16 +494,21 @@ int _tdb_transaction_cancel(struct tdb_context *tdb, int ltype) if (tdb->transaction->magic_offset) { const struct tdb_methods *methods = tdb->transaction->io_methods; - uint32_t zero = 0; + uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC; /* remove the recovery marker */ - if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &zero, 4) == -1 || + if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 || transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) { TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n")); ret = -1; } } + 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, @@ -797,7 +805,7 @@ static int transaction_setup_recovery(struct tdb_context *tdb, rec = (struct tdb_record *)data; memset(rec, 0, sizeof(*rec)); - rec->magic = 0; + rec->magic = TDB_RECOVERY_INVALID_MAGIC; rec->data_len = recovery_size; rec->rec_len = recovery_max_size; rec->key_len = old_map_size; @@ -960,11 +968,12 @@ static int _tdb_transaction_prepare_commit(struct tdb_context *tdb) 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")); - tdb_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 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_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 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_brunlock(tdb, F_WRLCK, GLOBAL_LOCK, 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; } - 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