From: Andrew Tridgell Date: Sat, 5 May 2007 07:14:33 +0000 (+1000) Subject: added tdb_chainlock_mark() call, which can be used to mark a chain locked without... X-Git-Tag: tevent-0.9.20~348^2~2775 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d903e9542d6e04f757d523774098807259e83561;p=thirdparty%2Fsamba.git added tdb_chainlock_mark() call, which can be used to mark a chain locked without actually locking it. This will be used to guarantee forward progress in the ctdb non-blocking lockwait code (This used to be ctdb commit 2af98c3418496b39106c7282f550049ec8239657) --- diff --git a/ctdb/lib/tdb/common/lock.c b/ctdb/lib/tdb/common/lock.c index 14ccbe39765..140d17818c4 100644 --- a/ctdb/lib/tdb/common/lock.c +++ b/ctdb/lib/tdb/common/lock.c @@ -28,6 +28,8 @@ #include "tdb_private.h" +#define TDB_MARK_LOCK 0x80000000 + /* a byte range locking function - return 0 on success this functions locks/unlocks 1 byte at the specified offset. @@ -109,6 +111,9 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) { struct tdb_lock_type *new_lck; int i; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; /* a global lock allows us to avoid per chain locks */ if (tdb->global_lock.count && @@ -158,7 +163,8 @@ static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op) /* Since fcntl locks don't nest, we do a lock for the first one, and simply bump the count for future ones */ - if (tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list,ltype, op, + if (!mark_lock && + tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op, 0, 1)) { return -1; } @@ -200,6 +206,9 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) int ret = -1; int i; struct tdb_lock_type *lck = NULL; + bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK); + + ltype &= ~TDB_MARK_LOCK; /* a global lock allows us to avoid per chain locks */ if (tdb->global_lock.count && @@ -244,8 +253,12 @@ int tdb_unlock(struct tdb_context *tdb, int list, int ltype) * anyway. */ - ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, - F_SETLKW, 0, 1); + if (mark_lock) { + ret = 0; + } else { + ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK, + F_SETLKW, 0, 1); + } tdb->num_locks--; /* @@ -376,6 +389,18 @@ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key) return tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); } +/* mark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); +} + +/* unmark a chain as locked without actually locking it. Warning! use with great caution! */ +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key) +{ + return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK); +} + int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key) { return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK); diff --git a/ctdb/lib/tdb/include/tdb.h b/ctdb/lib/tdb/include/tdb.h index b3f6a840b94..36fc0b405a6 100644 --- a/ctdb/lib/tdb/include/tdb.h +++ b/ctdb/lib/tdb/include/tdb.h @@ -140,6 +140,8 @@ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key); int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key); int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key); int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key); +int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key); /* Debug functions. Not used in production. */ void tdb_dump_all(struct tdb_context *tdb);