diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-07-29 14:53:03 +0930 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-08-04 16:43:34 +0930 |
commit | 6aa98fb041207bba4b84973c43689f0b9cfc29ce (patch) | |
tree | c4a9f4fe06d327290632b729f53dd8cbd0a04276 /ctdb/lib/tdb/common | |
parent | 825391de1d0a26d58e20caff7f049519302d51a9 (diff) | |
download | samba-6aa98fb041207bba4b84973c43689f0b9cfc29ce.tar.gz samba-6aa98fb041207bba4b84973c43689f0b9cfc29ce.tar.xz samba-6aa98fb041207bba4b84973c43689f0b9cfc29ce.zip |
Port from SAMBA tdb: commit 54a51839ea65aa788b18fce8de0ae4f9ba63e4e7 Author: Rusty Russell <rusty@rustcorp.com.au> Date: Sat Jul 18 15:28:58 2009 +0930
Make tdb transaction lock recursive (samba version)
This patch replaces 6ed27edbcd3ba1893636a8072c8d7a621437daf7 and
1a416ff13ca7786f2e8d24c66addf00883e9cb12, which fixed the bug where traversals
inside transactions would release the transaction lock early.
This solution is more general, and solves the more minor symptom that nested
traversals would also release the transaction lock early. (It was also suggestd in
Volker's comment in 6ed27ed).
This patch also applies to ctdb, if the traverse.c part is removed (ctdb's tdb
code never received the previous two fixes).
Tested using the testsuite from ccan (adapted to the samba code). Thanks to
Michael Adam for feedback.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Michael Adam <obnox@samba.org>
commit 760104188d0d2ed96ec4a70138e6d0bf86d797ed
Author: Rusty Russell <rusty@rustcorp.com.au>
Date: Tue Jul 21 16:23:35 2009 +0930
tdb: fix locking error
54a51839ea65aa788b18fce8de0ae4f9ba63e4e7 "Make tdb transaction lock
recursive (samba version)" was broken: I "cleaned it up" and prevented
it from ever unlocking.
To see the problem:
$ bin/tdbtorture -s 1248142523
tdb_brlock failed (fd=3) at offset 8 rw_type=1 lck_type=14 len=1
tdb_transaction_lock: failed to get transaction lock
tdb_transaction_start failed: Resource deadlock avoided
My testcase relied on the *count* being correct, which it was. Fixing that
now.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Michael Adam <obnox@samba.org>
(This used to be ctdb commit ce19658ba13272238058e9b9bc03e62f48b737c0)
Diffstat (limited to 'ctdb/lib/tdb/common')
-rw-r--r-- | ctdb/lib/tdb/common/lock.c | 17 | ||||
-rw-r--r-- | ctdb/lib/tdb/common/tdb_private.h | 2 |
2 files changed, 14 insertions, 5 deletions
diff --git a/ctdb/lib/tdb/common/lock.c b/ctdb/lib/tdb/common/lock.c index f156c0fa7b2..2c72ae1f0de 100644 --- a/ctdb/lib/tdb/common/lock.c +++ b/ctdb/lib/tdb/common/lock.c @@ -301,16 +301,21 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) */ int tdb_transaction_lock(struct tdb_context *tdb, int ltype) { - if (tdb->have_transaction_lock || tdb->global_lock.count) { + if (tdb->global_lock.count) { + return 0; + } + if (tdb->transaction_lock_count > 0) { + tdb->transaction_lock_count++; return 0; } + if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype, F_SETLKW, 0, 1) == -1) { TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n")); tdb->ecode = TDB_ERR_LOCK; return -1; } - tdb->have_transaction_lock = 1; + tdb->transaction_lock_count++; return 0; } @@ -320,12 +325,16 @@ int tdb_transaction_lock(struct tdb_context *tdb, int ltype) int tdb_transaction_unlock(struct tdb_context *tdb) { int ret; - if (!tdb->have_transaction_lock) { + if (tdb->global_lock.count) { + return 0; + } + if (tdb->transaction_lock_count > 1) { + tdb->transaction_lock_count--; return 0; } ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1); if (ret == 0) { - tdb->have_transaction_lock = 0; + tdb->transaction_lock_count = 0; } return ret; } diff --git a/ctdb/lib/tdb/common/tdb_private.h b/ctdb/lib/tdb/common/tdb_private.h index ffac89ff0e3..45b85f4c933 100644 --- a/ctdb/lib/tdb/common/tdb_private.h +++ b/ctdb/lib/tdb/common/tdb_private.h @@ -166,7 +166,7 @@ struct tdb_context { struct tdb_transaction *transaction; int page_size; int max_dead_records; - bool have_transaction_lock; + int transaction_lock_count; volatile sig_atomic_t *interrupt_sig_ptr; }; |