Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/tests/fs/vfs Add test case for F_GETLK pid-oddness from PR k...
details: https://anonhg.NetBSD.org/src/rev/1c9a68f2f235
branches: trunk
changeset: 761532:1c9a68f2f235
user: pooka <pooka%NetBSD.org@localhost>
date: Mon Jan 31 10:01:26 2011 +0000
description:
Add test case for F_GETLK pid-oddness from PR kern/44494.
I found the test case a little difficult to understand (because of
many indices), so I added a few more comments after I think I
figured out what was going on.
diffstat:
tests/fs/vfs/t_vnops.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 121 insertions(+), 1 deletions(-)
diffs (161 lines):
diff -r 73d00e19313c -r 1c9a68f2f235 tests/fs/vfs/t_vnops.c
--- a/tests/fs/vfs/t_vnops.c Mon Jan 31 09:57:29 2011 +0000
+++ b/tests/fs/vfs/t_vnops.c Mon Jan 31 10:01:26 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: t_vnops.c,v 1.12 2011/01/11 14:03:38 kefren Exp $ */
+/* $NetBSD: t_vnops.c,v 1.13 2011/01/31 10:01:26 pooka Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -29,10 +29,12 @@
#include <sys/stat.h>
#include <sys/statvfs.h>
+#include <assert.h>
#include <atf-c.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <rump/rump_syscalls.h>
@@ -567,6 +569,122 @@
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_pids(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];
+ pid_t prevpid = 0;
+
+ 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();
+
+ /*
+ * First, we create 4 processes and let each lock a range of the
+ * file. Note that the third and fourth processes lock in
+ * "reverse" order, i.e. the greater pid locks a range before
+ * the lesser pid.
+ */
+ for(i = 0; i < __arraycount(lwp); i++) {
+ RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
+
+ lwp[i] = rump_pub_lwproc_curlwp();
+ assert(rump_sys_getpid() > prevpid);
+ prevpid = rump_sys_getpid();
+
+ 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]));
+ }
+
+ atf_tc_expect_fail("PR kern/44494");
+ /*
+ * In the context of each pid , do GETLK for a readlock from
+ * i = [0,__arraycount(locks)]. If we try to lock from the same
+ * start offset as the lock our current process holds, check
+ * that we fail on the offset of the next lock ("else if" branch).
+ * Otherwise, expect to get a lock for the current offset
+ * ("if" branch). The "else" branch is purely for the last
+ * process where we expect no blocking locks.
+ */
+ 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) {
+ /*
+ * 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);
+ }
+ }
+ }
+
+ /*
+ * Release processes. This also releases the fds and locks
+ * making fs unmount possible
+ */
+ for(i = 0; i < __arraycount(lwp); i++) {
+ rump_pub_lwproc_switch(lwp[i]);
+ 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 +697,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_pids,"fcntl F_GETLK w/ many procs, PR kern/44494");
ATF_TP_ADD_TCS(tp)
{
@@ -595,6 +714,7 @@
ATF_TP_FSAPPLY(symlink_zerolen);
ATF_TP_FSAPPLY(attrs);
ATF_TP_FSAPPLY(fcntl_lock);
+ ATF_TP_FSAPPLY(fcntl_getlock_pids);
return atf_no_error();
}
Home |
Main Index |
Thread Index |
Old Index