[PATCH] lib/tdb: TDB_ALLOW_NESTING flag (port from ctdb)
Rusty Russell
rusty at rustcorp.com.au
Mon Aug 10 01:48:45 MDT 2009
Ported from ctdb change 3e49e41c21eb8c53084aa8cc7fd3557bdd8eb7b6
("New attempt at TDB transaction nesting allow/disallow").
Unfortunately, this is an API change if you were using nested transactions.
I've added the flag where needed to make quicktest (source4) and test
(source3) pass again.
As a general rule, nested transactions are dangerous: if you don't know you're
nesting, you can do a tdb_transaction_commit() which "succeeds", then gets
wiped by a crash, close, or outer tdb_transaction_cancel().
Signed-off-by: Rusty Russell <rusty at rustcorp.com.au>
diff --git a/lib/tdb/common/transaction.c b/lib/tdb/common/transaction.c
index e97fe67..d6d34fb 100644
--- a/lib/tdb/common/transaction.c
+++ b/lib/tdb/common/transaction.c
@@ -85,6 +85,13 @@
still available, but no transaction recovery area is used and no
fsync/msync calls are made.
+ - if TDB_ALLOW_NESTING is passed to flags in tdb open, or added using
+ tdb_add_flags() transaction is enabled.
+ The default is that transaction nesting is not allowed and an attempt
+ to create a nested transaction will fail with TDB_ERR_NESTING.
+
+ Beware. when transactions are nested a transaction successfully
+ completed with tdb_transaction_commit() can be silently unrolled later.
*/
@@ -434,6 +441,10 @@ int tdb_transaction_start(struct tdb_context *tdb)
/* cope with nested tdb_transaction_start() calls */
if (tdb->transaction != NULL) {
+ if (!(tdb->flags & TDB_ALLOW_NESTING)) {
+ tdb->ecode = TDB_ERR_NESTING;
+ return -1;
+ }
tdb->transaction->nesting++;
TDB_LOG((tdb, TDB_DEBUG_TRACE, "tdb_transaction_start: nesting %d\n",
tdb->transaction->nesting));
diff --git a/lib/tdb/include/tdb.h b/lib/tdb/include/tdb.h
index 22496f5..c55ac6d 100644
--- a/lib/tdb/include/tdb.h
+++ b/lib/tdb/include/tdb.h
@@ -48,13 +48,15 @@ extern "C" {
#define TDB_NOSYNC 64 /* don't use synchronous transactions */
#define TDB_SEQNUM 128 /* maintain a sequence number */
#define TDB_VOLATILE 256 /* Activate the per-hashchain freelist, default 5 */
+#define TDB_ALLOW_NESTING 512 /* Allow transactions to nest */
#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
/* error codes */
enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
- TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY};
+ TDB_ERR_NOEXIST, TDB_ERR_EINVAL, TDB_ERR_RDONLY,
+ TDB_ERR_NESTING};
/* debugging uses one of the following levels */
enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR,
diff --git a/source3/include/reg_db.h b/source3/include/reg_db.h
index 5cafa0a..a1a83f2 100644
--- a/source3/include/reg_db.h
+++ b/source3/include/reg_db.h
@@ -20,7 +20,7 @@
#ifndef _REG_DB_H
#define _REG_DB_H
-#define REG_TDB_FLAGS TDB_SEQNUM
+#define REG_TDB_FLAGS (TDB_SEQNUM|TDB_ALLOW_NESTING)
#define REGVER_V1 1 /* first db version with write support */
diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c
index f4101e9..bb2ac69 100644
--- a/source3/lib/account_pol.c
+++ b/source3/lib/account_pol.c
@@ -212,8 +212,8 @@ bool init_account_policy(void)
return True;
}
- db = db_open(NULL, state_path("account_policy.tdb"), 0, TDB_DEFAULT,
- O_RDWR, 0600);
+ db = db_open(NULL, state_path("account_policy.tdb"), 0,
+ TDB_ALLOW_NESTING, O_RDWR, 0600);
if (db == NULL) { /* the account policies files does not exist or open
* failed, try to create a new one */
diff --git a/source3/lib/ldb/ldb_tdb/ldb_tdb.c b/source3/lib/ldb/ldb_tdb/ldb_tdb.c
index 27cc0c6..7811791 100644
--- a/source3/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source3/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -64,6 +64,7 @@ static int ltdb_err_map(enum TDB_ERROR tdb_code)
return LDB_ERR_PROTOCOL_ERROR;
case TDB_ERR_LOCK:
case TDB_ERR_NOLOCK:
+ case TDB_ERR_NESTING:
return LDB_ERR_BUSY;
case TDB_ERR_LOCK_TIMEOUT:
return LDB_ERR_TIME_LIMIT_EXCEEDED;
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index b063f07..5ea9441 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -65,7 +65,7 @@ bool secrets_init(void)
}
db_ctx = db_open(NULL, fname, 0,
- TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+ TDB_ALLOW_NESTING, O_RDWR|O_CREAT, 0600);
if (db_ctx == NULL) {
DEBUG(0,("Failed to open %s\n", fname));
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index d4f7b45..c179c07 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -1246,7 +1246,7 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
path = url;
}
- tdb_flags = TDB_DEFAULT | TDB_SEQNUM;
+ tdb_flags = TDB_DEFAULT | TDB_SEQNUM | TDB_ALLOW_NESTING;
/* check for the 'nosync' option */
if (flags & LDB_FLG_NOSYNC) {
More information about the samba-technical
mailing list