NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/44494: F_GETLCK doesn't see some locks
>Number: 44494
>Category: kern
>Synopsis: F_GETLCK doesn't see some locks
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Jan 31 00:40:00 +0000 2011
>Originator: Alexander Nasonov
>Release: NetBSD 5.99.44 amd64
>Organization:
home sweet home
>Environment:
NetBSD nebeda.localdomain 5.99.44 NetBSD 5.99.44 (GENERIC) #0: Tue Jan 25
21:26:14 GMT 2011
root%nebeda.localdomain@localhost:/home/alnsn/src/netbsd-current/src/sys/arch/amd64/compile/obj/GENERIC
amd64
>Description:
When you start processes one by one and each process locks one byte at getpid()
offset for writing in a shared file (on tmpfs in case it matters) and then some
process walks through the file trying to enumerate all processes it misses
some. Everything is fine when pids are increasing but if a pid of some process
is lower than a pid of the preceding process, the lower pid will not be
enumerated.
>How-To-Repeat:
I wrote a rump test:
Index: t_vnops.c
===================================================================
RCS file: /cvsroot/src/tests/fs/vfs/t_vnops.c,v
retrieving revision 1.12
diff -u -u -r1.12 t_vnops.c
--- t_vnops.c 11 Jan 2011 14:03:38 -0000 1.12
+++ t_vnops.c 31 Jan 2011 00:21:33 -0000
@@ -33,6 +33,7 @@
#include <fcntl.h>
#include <libgen.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <rump/rump_syscalls.h>
@@ -567,6 +568,99 @@
FSTEST_EXIT();
}
+static int
+flock_compare(const void *p, const void *q)
+{
+ int a = ((const struct flock *)p)->l_start;
+ int b = ((const struct flock *)q)->l_start;
+ return a < b ? -1 : (a > b ? 1 : 0);
+}
+
+static void
+fcntl_getlock(const atf_tc_t *tc, const char *mp)
+{
+ /* test non-overlaping ranges */
+ struct flock expect[4];
+ const struct flock lock[4] = {
+ { 0, 2, 0, F_WRLCK, SEEK_SET },
+ { 2, 1, 0, F_WRLCK, SEEK_SET },
+ { 7, 5, 0, F_WRLCK, SEEK_SET },
+ { 4, 3, 0, F_WRLCK, SEEK_SET },
+ };
+
+ int fd[4];
+ struct lwp *lwp[4];
+
+ unsigned int i, j;
+ const off_t sz = 8192;
+ int omode = 0755;
+ int oflags = O_RDWR | O_CREAT;
+
+ memcpy(expect, lock, sizeof(lock));
+ qsort(expect, __arraycount(expect), sizeof(expect[0]), &flock_compare);
+
+ FSTEST_ENTER();
+
+ for(i = 0; i < __arraycount(lwp); i++) {
+ if(i != 0)
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+
+ lwp[i] = rump_pub_lwproc_curlwp();
+
+ RL(fd[i] = rump_sys_open(TESTFILE, oflags, omode));
+ oflags = O_RDWR;
+ omode = 0;
+
+ RL(rump_sys_ftruncate(fd[i], sz));
+ RL(rump_sys_fcntl(fd[i], F_SETLK, &lock[i]));
+ }
+
+ for(i = 0; i < __arraycount(lwp); i++) {
+ rump_pub_lwproc_switch(lwp[i]);
+
+ for(j = 0; j < __arraycount(lwp); j++) {
+ struct flock l;
+ l = expect[j];
+ l.l_len = sz;
+ l.l_type = F_RDLCK;
+
+ RL(rump_sys_fcntl(fd[i], F_GETLK, &l));
+
+ if(expect[j].l_start != lock[i].l_start) {
+ /* lock set by another process */
+ ATF_CHECK(l.l_type != F_UNLCK);
+ ATF_CHECK_EQ(l.l_start, expect[j].l_start);
+ ATF_CHECK_EQ(l.l_len, expect[j].l_len);
+ } else if(j != __arraycount(lwp) - 1) {
+ /* skip the lock set by the current process */
+ ATF_CHECK(l.l_type != F_UNLCK);
+ ATF_CHECK_EQ(l.l_start, expect[j+1].l_start);
+ ATF_CHECK_EQ(l.l_len, expect[j+1].l_len);
+ } else {
+ /* there are no other locks after the current
process lock */
+ ATF_CHECK_EQ(l.l_type, F_UNLCK);
+ ATF_CHECK_EQ(l.l_start, expect[j].l_start);
+ ATF_CHECK_EQ(l.l_len, sz);
+ ATF_CHECK_EQ(l.l_pid, expect[j].l_pid);
+ ATF_CHECK_EQ(l.l_whence, expect[j].l_whence);
+ }
+ }
+ }
+
+ rump_pub_lwproc_switch(lwp[0]);
+ for(i = __arraycount(lwp); i > 0; i--) {
+ rump_pub_lwproc_switch(lwp[i-1]);
+ RL(rump_sys_close(fd[i-1]));
+ }
+
+ for(i = __arraycount(lwp); i > 1; i--) {
+ rump_pub_lwproc_switch(lwp[i-1]);
+ rump_pub_lwproc_releaselwp();
+ }
+
+ FSTEST_EXIT();
+}
+
ATF_TC_FSAPPLY(lookup_simple, "simple lookup (./.. on root)");
ATF_TC_FSAPPLY(lookup_complex, "lookup of non-dot entries");
ATF_TC_FSAPPLY(dir_simple, "mkdir/rmdir");
@@ -579,6 +673,7 @@
ATF_TC_FSAPPLY(symlink_zerolen, "symlink with 0-len target");
ATF_TC_FSAPPLY(attrs, "check setting attributes works");
ATF_TC_FSAPPLY(fcntl_lock, "check fcntl F_SETLK");
+ATF_TC_FSAPPLY(fcntl_getlock, "check fcntl F_GETLK");
ATF_TP_ADD_TCS(tp)
{
@@ -595,6 +690,7 @@
ATF_TP_FSAPPLY(symlink_zerolen);
ATF_TP_FSAPPLY(attrs);
ATF_TP_FSAPPLY(fcntl_lock);
+ ATF_TP_FSAPPLY(fcntl_getlock);
return atf_no_error();
}
>Fix:
Home |
Main Index |
Thread Index |
Old Index