]> git.ozlabs.org Git - ccan-lca-2011.git/blobdiff - ccan/tdb2/free.c
tdb2: relax locking to allow two free list locks at once
[ccan-lca-2011.git] / ccan / tdb2 / free.c
index 13db5933911073577e42d1175fcecd5b7da12efb..a854aadfb6a3b25f763062ba8acea18a20a5d7f1 100644 (file)
@@ -450,15 +450,17 @@ again:
                if (tdb_write_convert(tdb, best_off, &rec, sizeof(rec)) != 0)
                        goto unlock_err;
 
-               tdb_unlock_free_bucket(tdb, b_off);
-
+               /* Bucket of leftover will be <= current bucket, so nested
+                * locking is allowed. */
                if (leftover) {
                        if (add_free_record(tdb,
                                            best_off + sizeof(rec)
                                            + frec_len(&best) - leftover,
                                            leftover))
-                               return TDB_OFF_ERR;
+                               best_off = TDB_OFF_ERR;
                }
+               tdb_unlock_free_bucket(tdb, b_off);
+
                return best_off;
        }
 
@@ -566,6 +568,14 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
                return -1;
        }
 
+       /* always make room for at least 100 more records, and at
+           least 25% more space. */
+       if (size * TDB_EXTENSION_FACTOR > tdb->map_size / 4)
+               wanted = size * TDB_EXTENSION_FACTOR;
+       else
+               wanted = tdb->map_size / 4;
+       wanted = adjust_size(0, wanted);
+
        /* Only one person can expand file at a time. */
        if (tdb_lock_expand(tdb, F_WRLCK) != 0)
                return -1;
@@ -578,7 +588,7 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
                return 0;
        }
 
-       if (tdb->methods->expand_file(tdb, wanted*TDB_EXTENSION_FACTOR) == -1) {
+       if (tdb->methods->expand_file(tdb, wanted) == -1) {
                tdb_unlock_expand(tdb, F_WRLCK);
                return -1;
        }
@@ -586,7 +596,7 @@ static int tdb_expand(struct tdb_context *tdb, tdb_len_t size)
        /* We need to drop this lock before adding free record. */
        tdb_unlock_expand(tdb, F_WRLCK);
 
-       return add_free_record(tdb, old_size, wanted * TDB_EXTENSION_FACTOR);
+       return add_free_record(tdb, old_size, wanted);
 }
 
 /* This won't fail: it will expand the database if it has to. */