1 /* We save the locks so we can reaquire them. */
6 #include <ccan/tap/tap.h>
7 #include <ccan/tdb/tdb_private.h>
15 static struct lock *locks;
16 int locking_errors = 0;
17 bool suppress_lockcheck = false;
18 void (*unlock_callback)(int fd);
20 int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ )
26 if (cmd != F_SETLK && cmd != F_SETLKW) {
27 /* This may be totally bogus, but we don't know in general. */
29 arg3 = va_arg(ap, int);
32 return fcntl(fd, cmd, arg3);
36 fl = va_arg(ap, struct flock *);
39 if (fl->l_type == F_UNLCK) {
41 struct lock *old = NULL;
43 for (l = &locks; *l; l = &(*l)->next) {
44 if ((*l)->off == fl->l_start
45 && (*l)->len == fl->l_len) {
52 if (!old && !suppress_lockcheck) {
53 diag("Unknown unlock %u@%u",
54 (int)fl->l_len, (int)fl->l_start);
59 unsigned int fl_end = fl->l_start + fl->l_len;
61 fl_end = (unsigned int)-1;
63 /* Check for overlaps: we shouldn't do this. */
64 for (i = locks; i; i = i->next) {
65 unsigned int i_end = i->off + i->len;
67 i_end = (unsigned int)-1;
69 if (fl->l_start >= i->off && fl->l_start < i_end)
71 if (fl_end >= i->off && fl_end < i_end)
74 /* tdb_allrecord_lock does this, handle adjacent: */
75 if (fl->l_start == i_end && fl->l_type == i->type) {
76 i->len = fl->l_len ? i->len + fl->l_len : 0;
81 /* Special case: upgrade of allrecord lock. */
82 if (i->type == F_RDLCK && fl->l_type == F_WRLCK
83 && i->off == FREELIST_TOP
84 && fl->l_start == FREELIST_TOP
90 if (!suppress_lockcheck) {
91 diag("%s lock %u@%u overlaps %u@%u",
92 fl->l_type == F_WRLCK ? "write" : "read",
93 (int)fl->l_len, (int)fl->l_start,
98 new = malloc(sizeof *new);
99 new->off = fl->l_start;
100 new->len = fl->l_len;
101 new->type = fl->l_type;
106 ret = fcntl(fd, cmd, fl);
107 if (ret == 0 && fl->l_type == F_UNLCK && unlock_callback)
112 int forget_locking(void)
114 unsigned int num = 0;
116 struct lock *next = locks->next;