summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2013-02-16 16:49:56 +0100
committerStefan Metzmacher <metze@samba.org>2013-02-19 15:46:45 +0100
commit3534e4e8d5bebfaaaef5886dcea219a7e4047fc7 (patch)
treef46e77c6cdc3b2ff74adee52dd753ff8c94ddf46 /lib
parent1f93f0836484ccc1abe335f5bd2cfd35df0b7631 (diff)
downloadsamba-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>
Diffstat (limited to 'lib')
-rw-r--r--lib/tdb/common/lock.c59
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;