#include <stdarg.h>
#include <stdlib.h>
#include <ccan/tap/tap.h>
+#include <ccan/tdb/tdb_private.h>
struct lock {
struct lock *next;
};
static struct lock *locks;
int locking_errors = 0;
+bool suppress_lockcheck = false;
void (*unlock_callback)(int fd);
int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ )
break;
}
}
- if (!old) {
+ if (!old && !suppress_lockcheck) {
diag("Unknown unlock %u@%u",
(int)fl->l_len, (int)fl->l_start);
locking_errors++;
break;
}
if (i) {
- diag("%s lock %u@%u overlaps %u@%u",
- fl->l_type == F_WRLCK ? "write" : "read",
- (int)fl->l_len, (int)fl->l_start,
- i->len, (int)i->off);
- locking_errors++;
+ /* Special case: upgrade of allrecord lock. */
+ if (i->type == F_RDLCK && fl->l_type == F_WRLCK
+ && i->off == FREELIST_TOP
+ && fl->l_start == FREELIST_TOP
+ && i->len == 0
+ && fl->l_len == 0) {
+ i->type = F_WRLCK;
+ goto ok;
+ }
+ if (!suppress_lockcheck) {
+ diag("%s lock %u@%u overlaps %u@%u",
+ fl->l_type == F_WRLCK ? "write" : "read",
+ (int)fl->l_len, (int)fl->l_start,
+ i->len, (int)i->off);
+ locking_errors++;
+ }
}
new = malloc(sizeof *new);
new->off = fl->l_start;
new->next = locks;
locks = new;
}
-
+ok:
ret = fcntl(fd, cmd, fl);
if (ret == 0 && fl->l_type == F_UNLCK && unlock_callback)
unlock_callback(fd);