]> git.ozlabs.org Git - ccan/blobdiff - ccan/tdb2/lock.c
tdb2: fix valgrind warnings.
[ccan] / ccan / tdb2 / lock.c
index 3230b25e383d3b2a3ead9a1ac7ca156b4030f303..c7c449abc1a37091824563475b7aa7558f89e759 100644 (file)
@@ -255,13 +255,18 @@ static int tdb_nest_lock(struct tdb_context *tdb, tdb_off_t offset, int ltype,
 {
        struct tdb_lock_type *new_lck;
 
-       if (offset >= TDB_HASH_LOCK_START + (1ULL << tdb->header.v.hash_bits)
-           + (tdb->header.v.num_zones * (tdb->header.v.free_buckets+1))) {
-               tdb->ecode = TDB_ERR_LOCK;
-               tdb->log(tdb, TDB_DEBUG_FATAL, tdb->log_priv,
-                        "tdb_lock: invalid offset %llu for ltype=%d\n",
-                        (long long)offset, ltype);
-               return -1;
+       /* Header is not valid for open lock; valgrind complains. */
+       if (offset >= TDB_HASH_LOCK_START) {
+               if (offset > TDB_HASH_LOCK_START
+                   + (1ULL << tdb->header.v.hash_bits)
+                   + (tdb->header.v.num_zones
+                      * (tdb->header.v.free_buckets+1))) {
+                       tdb->ecode = TDB_ERR_LOCK;
+                       tdb->log(tdb, TDB_DEBUG_FATAL, tdb->log_priv,
+                                "tdb_lock: invalid offset %llu ltype=%d\n",
+                                (long long)offset, ltype);
+                       return -1;
+               }
        }
        if (tdb->flags & TDB_NOLOCK)
                return 0;
@@ -485,8 +490,8 @@ int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
        /* Lock all the hash buckets. */
 again:
        hash_size = (1ULL << tdb->header.v.hash_bits);
-       if (tdb_lock_gradual(tdb, ltype, TDB_HASH_LOCK_START,
-                            1ULL << tdb->header.v.hash_bits, flags)) {
+       if (tdb_lock_gradual(tdb, ltype, flags, TDB_HASH_LOCK_START,
+                            hash_size)) {
                if (!(flags & TDB_LOCK_PROBE)) {
                        tdb->log(tdb, TDB_DEBUG_ERROR, tdb->log_priv,
                                 "tdb_lockall hashes failed (%s)\n",
@@ -665,6 +670,8 @@ again:
 
 int tdb_unlock_list(struct tdb_context *tdb, tdb_off_t list, int ltype)
 {
+       list &= ((1ULL << tdb->header.v.hash_bits) - 1);
+
        /* a allrecord lock allows us to avoid per chain locks */
        if (tdb->allrecord_lock.count) {
                if (tdb->allrecord_lock.ltype == F_RDLCK
@@ -717,7 +724,8 @@ void tdb_unlock_free_list(struct tdb_context *tdb, tdb_off_t flist)
                        + flist, F_WRLCK);
 }
 
-#if 0
+/* Even if the entry isn't in this hash bucket, you'd have to lock this
+ * bucket to find it. */
 static int chainlock(struct tdb_context *tdb, const TDB_DATA *key,
                     int ltype, enum tdb_lock_flags waitflag,
                     const char *func)
@@ -737,6 +745,14 @@ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
        return chainlock(tdb, &key, F_WRLCK, TDB_LOCK_WAIT, "tdb_chainlock");
 }
 
+int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
+{
+       uint64_t h = tdb_hash(tdb, key.dptr, key.dsize);
+       tdb_trace_1rec(tdb, "tdb_chainunlock", key);
+       return tdb_unlock_list(tdb, h, F_WRLCK);
+}
+
+#if 0
 /* lock/unlock one hash chain, non-blocking. This is meant to be used
    to reduce contention - it cannot guarantee how many records will be
    locked */
@@ -746,14 +762,6 @@ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
                         "tdb_chainlock_nonblock");
 }
 
-int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
-{
-       uint64_t h = tdb_hash(tdb, key.dptr, key.dsize);
-       tdb_trace_1rec(tdb, "tdb_chainunlock", key);
-       return tdb_unlock_list(tdb, h & ((1ULL << tdb->header.v.hash_bits)-1),
-                              F_WRLCK);
-}
-
 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
 {
        return chainlock(tdb, &key, F_RDLCK, TDB_LOCK_WAIT,