diff options
author | Volker Lendecke <vl@samba.org> | 2013-02-16 16:49:56 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2013-02-19 15:46:45 +0100 |
commit | 3534e4e8d5bebfaaaef5886dcea219a7e4047fc7 (patch) | |
tree | f46e77c6cdc3b2ff74adee52dd753ff8c94ddf46 | |
parent | 1f93f0836484ccc1abe335f5bd2cfd35df0b7631 (diff) | |
download | samba-3534e4e8d5bebfaaaef5886dcea219a7e4047fc7.tar.gz samba-3534e4e8d5bebfaaaef5886dcea219a7e4047fc7.tar.xz samba-3534e4e8d5bebfaaaef5886dcea219a7e4047fc7.zip |
tdb: Factor out the retry loop from tdb_allrecord_upgrade
For the mutex code we will have to lock the hashchain and the record
lock area independently. So we will have to call the loop twice. And,
it's a small refactoring for the better anyway I think.
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | lib/tdb/common/lock.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/lib/tdb/common/lock.c b/lib/tdb/common/lock.c index 16963df097..25ed877900 100644 --- a/lib/tdb/common/lock.c +++ b/lib/tdb/common/lock.c @@ -198,14 +198,42 @@ int tdb_brunlock(struct tdb_context *tdb, } /* - upgrade a read lock to a write lock. This needs to be handled in a - special way as some OSes (such as solaris) have too conservative - deadlock detection and claim a deadlock when progress can be - made. For those OSes we may loop for a while. + * Do a tdb_brlock in a loop. Some OSes (such as solaris) have too + * conservative deadlock detection and claim a deadlock when progress can be + * made. For those OSes we may loop for a while. + */ + +static int tdb_brlock_retry(struct tdb_context *tdb, + int rw_type, tdb_off_t offset, size_t len, + enum tdb_lock_flags flags) +{ + int count = 1000; + + while (count--) { + struct timeval tv; + int ret; + + ret = tdb_brlock(tdb, rw_type, offset, len, flags); + if (ret == 0) { + return 0; + } + if (errno != EDEADLK) { + break; + } + /* sleep for as short a time as we can - more portable than usleep() */ + tv.tv_sec = 0; + tv.tv_usec = 1; + select(0, NULL, NULL, NULL, &tv); + } + return -1; +} + +/* + upgrade a read lock to a write lock. */ int tdb_allrecord_upgrade(struct tdb_context *tdb) { - int count = 1000; + int ret; if (tdb->allrecord_lock.count != 1) { TDB_LOG((tdb, TDB_DEBUG_ERROR, @@ -220,21 +248,12 @@ int tdb_allrecord_upgrade(struct tdb_context *tdb) return -1; } - while (count--) { - struct timeval tv; - if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, - TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) { - tdb->allrecord_lock.ltype = F_WRLCK; - tdb->allrecord_lock.off = 0; - return 0; - } - if (errno != EDEADLK) { - break; - } - /* sleep for as short a time as we can - more portable than usleep() */ - tv.tv_sec = 0; - tv.tv_usec = 1; - select(0, NULL, NULL, NULL, &tv); + ret = tdb_brlock_retry(tdb, F_WRLCK, FREELIST_TOP, 0, + TDB_LOCK_WAIT|TDB_LOCK_PROBE); + if (ret == 0) { + tdb->allrecord_lock.ltype = F_WRLCK; + tdb->allrecord_lock.off = 0; + return 0; } TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n")); return -1; |