[SCM] Samba Shared Repository - branch master updated

Rusty Russell rusty at samba.org
Tue Feb 9 23:27:04 MST 2010


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 <rusty at 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 <rusty at rustcorp.com.au>

commit 6269cdcd1538e2e3cead9e0f3c156b0363d607a0
Author: Rusty Russell <rusty at 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 <rusty at 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


More information about the samba-cvs mailing list