diff options
author | Michael Adam <obnox@samba.org> | 2009-10-28 01:54:04 +0100 |
---|---|---|
committer | Karolin Seeger <kseeger@samba.org> | 2009-11-26 11:40:34 +0100 |
commit | d741eee4c90f0b6730b427d858740ddf0fff7fa7 (patch) | |
tree | 8a624bcdfe0935b88eb33f7f744b76ce1633f706 /source3/lib | |
parent | 114d73ff98c4be6c98d18b346bce228bacf18ba1 (diff) | |
download | samba-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.c | 25 |
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; |