X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb%2Ftest%2Flock-tracking.c;h=f6e97138e8b7f07b5b00336a9d7a0ed834d045d9;hp=8460c048dfcfb74d929153118293572162a78543;hb=a153d09b979182e8586d4501ea687bcdd466dabc;hpb=426c8dc977d0fb46286042f7072d86bc053836a1 diff --git a/ccan/tdb/test/lock-tracking.c b/ccan/tdb/test/lock-tracking.c index 8460c048..f6e97138 100644 --- a/ccan/tdb/test/lock-tracking.c +++ b/ccan/tdb/test/lock-tracking.c @@ -15,6 +15,8 @@ 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 */ ) @@ -22,6 +24,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. */ @@ -36,6 +39,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; @@ -43,15 +57,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 && !suppress_lockcheck) { - diag("Unknown unlock %u@%u", - (int)fl->l_len, (int)fl->l_start); + diag("Unknown unlock %u@%u - %i", + (int)fl->l_len, (int)fl->l_start, ret); locking_errors++; } } else { @@ -73,8 +89,12 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) /* tdb_allrecord_lock does this, handle adjacent: */ if (fl->l_start == i_end && fl->l_type == i->type) { - i->len = fl->l_len ? i->len + fl->l_len : 0; - goto ok; + if (ret == 0) { + i->len = fl->l_len + ? i->len + fl->l_len + : 0; + } + goto done; } } if (i) { @@ -84,8 +104,9 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) && fl->l_start == FREELIST_TOP && i->len == 0 && fl->l_len == 0) { - i->type = F_WRLCK; - goto ok; + if (ret == 0) + i->type = F_WRLCK; + goto done; } if (!suppress_lockcheck) { diag("%s lock %u@%u overlaps %u@%u", @@ -95,15 +116,17 @@ int fcntl_with_lockcheck(int fd, int cmd, ... /* arg */ ) 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; + + 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; + } } -ok: - ret = fcntl(fd, cmd, fl); +done: if (ret == 0 && fl->l_type == F_UNLCK && unlock_callback) unlock_callback(fd); return ret;