X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb%2Ftest%2Flock-tracking.c;h=8e8bb999c52df90ce01a444b4d987b511b2c2e16;hp=bc4be14759211f6718bfda34d124652329d3544a;hb=100444225380d3f5ca29424ea54703d308c7c651;hpb=c4a9fd1b01822e75da853d3f3229de5d35409e31 diff --git a/ccan/tdb/test/lock-tracking.c b/ccan/tdb/test/lock-tracking.c index bc4be147..8e8bb999 100644 --- a/ccan/tdb/test/lock-tracking.c +++ b/ccan/tdb/test/lock-tracking.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include "lock-tracking.h" struct lock { struct lock *next; @@ -13,6 +15,9 @@ struct lock { }; static struct lock *locks; int locking_errors = 0; +bool suppress_lockcheck = false; +bool nonblocking_locks; +int locking_would_block = 0; void (*unlock_callback)(int fd); int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) @@ -20,6 +25,7 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) va_list ap; int ret, arg3; struct flock *fl; + bool may_block = false; if (cmd != F_SETLK && cmd != F_SETLKW) { /* This may be totally bogus, but we don't know in general. */ @@ -34,6 +40,17 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) fl = va_arg(ap, struct flock *); va_end(ap); + if (cmd == F_SETLKW && nonblocking_locks) { + cmd = F_SETLK; + may_block = true; + } + ret = fcntl(fd, cmd, fl); + + /* Detect when we failed, but might have been OK if we waited. */ + if (may_block && ret == -1 && (errno == EAGAIN || errno == EACCES)) { + locking_would_block++; + } + if (fl->l_type == F_UNLCK) { struct lock **l; struct lock *old = NULL; @@ -41,15 +58,17 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) for (l = &locks; *l; l = &(*l)->next) { if ((*l)->off == fl->l_start && (*l)->len == fl->l_len) { - old = *l; - *l = (*l)->next; - free(old); + if (ret == 0) { + old = *l; + *l = (*l)->next; + free(old); + } break; } } - if (!old) { - diag("Unknown unlock %u@%u", - (int)fl->l_len, (int)fl->l_start); + if (!old && !suppress_lockcheck) { + diag("Unknown unlock %u@%u - %i", + (int)fl->l_len, (int)fl->l_start, ret); locking_errors++; } } else { @@ -68,29 +87,53 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) break; if (fl_end >= i->off && fl_end < i_end) break; + + /* tdb_allrecord_lock does this, handle adjacent: */ + if (fl->l_start == i_end && fl->l_type == i->type) { + if (ret == 0) { + i->len = fl->l_len + ? i->len + fl->l_len + : 0; + } + goto done; + } } 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) { + if (ret == 0) + i->type = F_WRLCK; + goto done; + } + 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->len = fl->l_len; - new->type = fl->l_type; - new->next = locks; - locks = new; - } - ret = fcntl(fd, cmd, fl); + if (ret == 0) { + new = malloc(sizeof *new); + new->off = fl->l_start; + new->len = fl->l_len; + new->type = fl->l_type; + new->next = locks; + locks = new; + } + } +done: if (ret == 0 && fl->l_type == F_UNLCK && unlock_callback) unlock_callback(fd); return ret; } -int forget_locking(void) +unsigned int forget_locking(void) { unsigned int num = 0; while (locks) {