tdb: suppress record write locks when allrecord lock is taken.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 23 Feb 2010 22:22:44 +0000 (08:52 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 23 Feb 2010 22:22:44 +0000 (08:52 +1030)
Records themselves get (read) locked by the traversal code against delete.
Interestingly, this locking isn't done when the allrecord lock has been
taken, though the allrecord lock until recently didn't cover the actual
records (it now goes to end of file).

The write record lock, grabbed by the delete code, is not suppressed by
the allrecord lock, which causes us to punch a hole in that lock when we
release the write record lock.  Make this consistent: *no* record locks
of any kind when the allrecord lock is taken.

ccan/tdb/lock.c

index a59ba365213e473630617ee69ff1f238585d6782..2a681efc9963afa9e2e3db7b7122f7e7beb3c65e 100644 (file)
@@ -662,11 +662,20 @@ int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off)
        for (i = &tdb->travlocks; i; i = i->next)
                if (i->off == off)
                        return -1;
+       if (tdb->allrecord_lock.count) {
+               if (tdb->allrecord_lock.ltype == F_WRLCK) {
+                       return 0;
+               }
+               return -1;
+       }
        return tdb->methods->brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
 }
 
 int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
 {
+       if (tdb->allrecord_lock.count) {
+               return 0;
+       }
        return tdb->methods->brunlock(tdb, F_WRLCK, off, 1);
 }