The branch, master has been updated via b37b452... tdb: fix recovery reuse after crash via 6269cdc... tdb: give a name to the invalid recovery area constant (0) from f299fe5... s4:provision Just 'do the right thing' with empty smb.conf files
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit b37b452cb8c1f56b37b04abe7bffdede371ca361 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Thu Feb 4 23:59:54 2010 +1030 tdb: fix recovery reuse after crash If a process (or the machine) dies after just after writing the recovery head (pointing at the end of file), the recovery record will filled with 0x42. This will not invoke a recovery on open, since rec.magic != TDB_RECOVERY_MAGIC. Unfortunately, the first transaction commit will happily reuse that area: tdb_recovery_allocate() doesn't check the magic. The recovery record has length 0x42424242, and it writes that back into the now-valid-looking transaction header) for the next comer (which happens to be tdb_wipe_all in my tests). Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> commit 6269cdcd1538e2e3cead9e0f3c156b0363d607a0 Author: Rusty Russell <ru...@rustcorp.com.au> Date: Fri Feb 5 00:00:24 2010 +1030 tdb: give a name to the invalid recovery area constant (0) Signed-off-by: Rusty Russell <ru...@rustcorp.com.au> ----------------------------------------------------------------------- Summary of changes: lib/tdb/common/check.c | 2 +- lib/tdb/common/tdb_private.h | 1 + lib/tdb/common/transaction.c | 20 +++++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/tdb/common/check.c b/lib/tdb/common/check.c index f0a15f8..6bbfd7d 100644 --- a/lib/tdb/common/check.c +++ b/lib/tdb/common/check.c @@ -370,7 +370,7 @@ int tdb_check(struct tdb_context *tdb, goto free; break; case TDB_RECOVERY_MAGIC: - case 0: /* Used for invalid (or in-progress) recovery area. */ + case TDB_RECOVERY_INVALID_MAGIC: if (recovery_start != off) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "Unexpected recovery record at offset %d\n", diff --git a/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h index be9be72..0e74b10 100644 --- a/lib/tdb/common/tdb_private.h +++ b/lib/tdb/common/tdb_private.h @@ -49,6 +49,7 @@ typedef uint32_t tdb_off_t; #define TDB_FREE_MAGIC (~TDB_MAGIC) #define TDB_DEAD_MAGIC (0xFEE1DEAD) #define TDB_RECOVERY_MAGIC (0xf53bc0e7U) +#define TDB_RECOVERY_INVALID_MAGIC (0x0) #define TDB_ALIGNMENT 4 #define DEFAULT_HASH_SIZE 131 #define FREELIST_TOP (sizeof(struct tdb_header)) diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c index b8988ea..67104ef 100644 --- a/lib/tdb/common/transaction.c +++ b/lib/tdb/common/transaction.c @@ -596,10 +596,10 @@ int _tdb_transaction_cancel(struct tdb_context *tdb) 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; @@ -695,10 +695,16 @@ static int tdb_recovery_allocate(struct tdb_context *tdb, rec.rec_len = 0; - if (recovery_head != 0 && - methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); - return -1; + if (recovery_head != 0) { + if (methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n")); + return -1; + } + /* ignore invalid recovery regions: can happen in crash */ + if (rec.magic != TDB_RECOVERY_MAGIC && + rec.magic != TDB_RECOVERY_INVALID_MAGIC) { + recovery_head = 0; + } } *recovery_size = tdb_recovery_size(tdb); @@ -793,7 +799,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; -- Samba Shared Repository