[PATCH] Make tdb transaction lock recursive (samba version)
Michael Adam
obnox at samba.org
Mon Jul 20 14:20:35 MDT 2009
Pushed to master - thanks!
Rusty Russell wrote:
> 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 at rustcorp.com.au>
>
> diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c
> index f156c0f..d812fbf 100644
> --- a/lib/tdb/common/lock.c
> +++ b/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 > 0) {
> + 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/lib/tdb/common/tdb_private.h b/lib/tdb/common/tdb_private.h
> index ffac89f..b9a1145 100644
> --- a/lib/tdb/common/tdb_private.h
> +++ b/lib/tdb/common/tdb_private.h
> @@ -166,7 +168,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;
> };
>
> diff --git a/lib/tdb/common/traverse.c b/lib/tdb/common/traverse.c
> index 69c81e6..07b0c23 100644
> --- a/lib/tdb/common/traverse.c
> +++ b/lib/tdb/common/traverse.c
> @@ -204,23 +204,18 @@ int tdb_traverse_read(struct tdb_context *tdb,
> {
> struct tdb_traverse_lock tl = { NULL, 0, 0, F_RDLCK };
> int ret;
> - bool in_transaction = (tdb->transaction != NULL);
>
> /* we need to get a read lock on the transaction lock here to
> cope with the lock ordering semantics of solaris10 */
> - if (!in_transaction) {
> - if (tdb_transaction_lock(tdb, F_RDLCK)) {
> - return -1;
> - }
> + if (tdb_transaction_lock(tdb, F_RDLCK)) {
> + return -1;
> }
>
> tdb->traverse_read++;
> ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
> tdb->traverse_read--;
>
> - if (!in_transaction) {
> - tdb_transaction_unlock(tdb);
> - }
> + tdb_transaction_unlock(tdb);
>
> return ret;
> }
> @@ -237,25 +232,20 @@ int tdb_traverse(struct tdb_context *tdb,
> {
> struct tdb_traverse_lock tl = { NULL, 0, 0, F_WRLCK };
> int ret;
> - bool in_transaction = (tdb->transaction != NULL);
>
> if (tdb->read_only || tdb->traverse_read) {
> return tdb_traverse_read(tdb, fn, private_data);
> }
>
> - if (!in_transaction) {
> - if (tdb_transaction_lock(tdb, F_WRLCK)) {
> - return -1;
> - }
> + if (tdb_transaction_lock(tdb, F_WRLCK)) {
> + return -1;
> }
>
> tdb->traverse_write++;
> ret = tdb_traverse_internal(tdb, fn, private_data, &tl);
> tdb->traverse_write--;
>
> - if (!in_transaction) {
> - tdb_transaction_unlock(tdb);
> - }
> + tdb_transaction_unlock(tdb);
>
> return ret;
> }
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 206 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20090720/81eb97e5/attachment.pgp>
More information about the samba-technical
mailing list