summaryrefslogtreecommitdiffstats
path: root/source3/lib
diff options
context:
space:
mode:
authorMichael Adam <obnox@samba.org>2009-10-28 01:54:04 +0100
committerKarolin Seeger <kseeger@samba.org>2009-11-26 11:40:34 +0100
commitd741eee4c90f0b6730b427d858740ddf0fff7fa7 (patch)
tree8a624bcdfe0935b88eb33f7f744b76ce1633f706 /source3/lib
parent114d73ff98c4be6c98d18b346bce228bacf18ba1 (diff)
downloadsamba-d741eee4c90f0b6730b427d858740ddf0fff7fa7.tar.gz
samba-d741eee4c90f0b6730b427d858740ddf0fff7fa7.tar.xz
samba-d741eee4c90f0b6730b427d858740ddf0fff7fa7.zip
s3:dbwrap_ctdb: fix a race in starting concurrent transactions on a single node
There are two races in concurrent transactions on a single node. One in starting a transaction and one with replay during commit. This commit closes the first race by storing the client pid in the transaction-lock record and comparing the stored pid against its own pid after releasing the lock and refetching the record inside the transaction. Michael Signed-off-by: Michael Adam <obnox@samba.org> (cherry picked from commit 7b37b8a5dcc08817b21e12570da6632674cc7575)
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/dbwrap_ctdb.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/source3/lib/dbwrap_ctdb.c b/source3/lib/dbwrap_ctdb.c
index fce6126a5c0..49df62afd30 100644
--- a/source3/lib/dbwrap_ctdb.c
+++ b/source3/lib/dbwrap_ctdb.c
@@ -316,12 +316,14 @@ static int db_ctdb_transaction_destructor(struct db_ctdb_transaction_handle *h)
static int db_ctdb_transaction_fetch_start(struct db_ctdb_transaction_handle *h)
{
struct db_record *rh;
+ struct db_ctdb_rec *crec;
TDB_DATA key;
TALLOC_CTX *tmp_ctx;
const char *keyname = CTDB_TRANSACTION_LOCK_KEY;
int ret;
struct db_ctdb_ctx *ctx = h->ctx;
TDB_DATA data;
+ pid_t pid;
NTSTATUS status;
struct ctdb_ltdb_header header;
@@ -337,6 +339,23 @@ again:
talloc_free(tmp_ctx);
return -1;
}
+ crec = talloc_get_type_abort(rh->private_data, struct db_ctdb_rec);
+
+ /*
+ * store the pid in the database:
+ * it is not enought that the node is dmaster...
+ */
+ pid = getpid();
+ data.dptr = (unsigned char *)&pid;
+ data.dsize = sizeof(pid_t);
+ status = db_ctdb_ltdb_store(ctx, key, &(crec->header), data);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, (__location__ " Failed to store pid in transaction "
+ "record: %s\n", nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
talloc_free(rh);
ret = tdb_transaction_start(ctx->wtdb->tdb);
@@ -353,6 +372,12 @@ again:
goto again;
}
+ if ((data.dsize != sizeof(pid_t)) || (*(pid_t *)(data.dptr) != pid)) {
+ tdb_transaction_cancel(ctx->wtdb->tdb);
+ talloc_free(tmp_ctx);
+ goto again;
+ }
+
talloc_free(tmp_ctx);
return 0;