diff options
| author | Alan Somers <asomers@FreeBSD.org> | 2019-07-18 17:55:13 +0000 |
|---|---|---|
| committer | Alan Somers <asomers@FreeBSD.org> | 2019-07-18 17:55:13 +0000 |
| commit | ed74f781c9f704092556f860a00b0bb53fdedff7 (patch) | |
| tree | a0debdb972a97d02e135b2ba8ed5940f64fc87b2 /tests | |
| parent | f05962453e84168a0c0e616372bc99f10754a947 (diff) | |
Notes
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/sys/fs/fusefs/interrupt.cc | 75 | ||||
| -rw-r--r-- | tests/sys/fs/fusefs/mockfs.cc | 9 | ||||
| -rw-r--r-- | tests/sys/fs/fusefs/mockfs.hh | 2 | ||||
| -rw-r--r-- | tests/sys/fs/fusefs/utils.cc | 3 | ||||
| -rw-r--r-- | tests/sys/fs/fusefs/utils.hh | 2 |
5 files changed, 79 insertions, 12 deletions
diff --git a/tests/sys/fs/fusefs/interrupt.cc b/tests/sys/fs/fusefs/interrupt.cc index 98841db778506..9a2e55241dadc 100644 --- a/tests/sys/fs/fusefs/interrupt.cc +++ b/tests/sys/fs/fusefs/interrupt.cc @@ -185,6 +185,15 @@ void TearDown() { } }; +class Intr: public Interrupt {}; + +class Nointr: public Interrupt { + void SetUp() { + m_nointr = true; + Interrupt::SetUp(); + } +}; + static void* mkdir0(void* arg __unused) { ssize_t r; @@ -213,7 +222,7 @@ static void* read1(void* arg) { * complete should generate an EAGAIN response. */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ -TEST_F(Interrupt, already_complete) +TEST_F(Intr, already_complete) { uint64_t ino = 42; pthread_t self; @@ -271,7 +280,7 @@ TEST_F(Interrupt, already_complete) * kernel should not attempt to interrupt any other operations on that mount * point. */ -TEST_F(Interrupt, enosys) +TEST_F(Intr, enosys) { uint64_t ino0 = 42, ino1 = 43;; uint64_t mkdir_unique; @@ -356,7 +365,7 @@ TEST_F(Interrupt, enosys) * complete the original operation whenever it damn well pleases. */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ -TEST_F(Interrupt, ignore) +TEST_F(Intr, ignore) { uint64_t ino = 42; pthread_t self; @@ -392,7 +401,7 @@ TEST_F(Interrupt, ignore) * that hasn't yet been sent to userland can be interrupted without sending * FUSE_INTERRUPT, and will be automatically restarted. */ -TEST_F(Interrupt, in_kernel_restartable) +TEST_F(Intr, in_kernel_restartable) { const char FULLPATH1[] = "mountpoint/other_file.txt"; const char RELPATH1[] = "other_file.txt"; @@ -462,7 +471,7 @@ TEST_F(Interrupt, in_kernel_restartable) * without sending FUSE_INTERRUPT. If it's a non-restartable operation (write * or setextattr) it will return EINTR. */ -TEST_F(Interrupt, in_kernel_nonrestartable) +TEST_F(Intr, in_kernel_nonrestartable) { const char FULLPATH1[] = "mountpoint/other_file.txt"; const char RELPATH1[] = "other_file.txt"; @@ -533,7 +542,7 @@ TEST_F(Interrupt, in_kernel_nonrestartable) * return EINTR to userspace */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ -TEST_F(Interrupt, in_progress) +TEST_F(Intr, in_progress) { pthread_t self; uint64_t mkdir_unique; @@ -563,7 +572,7 @@ TEST_F(Interrupt, in_progress) } /* Reads should also be interruptible */ -TEST_F(Interrupt, in_progress_read) +TEST_F(Intr, in_progress_read) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; @@ -601,8 +610,56 @@ TEST_F(Interrupt, in_progress_read) EXPECT_EQ(EINTR, errno); } +/* + * When mounted with -o nointr, fusefs will block signals while waiting for the + * server. + */ +TEST_F(Nointr, block) +{ + uint64_t ino = 42; + pthread_t self; + sem_t sem0; + + ASSERT_EQ(0, sem_init(&sem0, 0, 0)) << strerror(errno); + signaled_semaphore = &sem0; + self = pthread_self(); + + EXPECT_LOOKUP(FUSE_ROOT_ID, RELDIRPATH0) + .WillOnce(Invoke(ReturnErrno(ENOENT))); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in.header.opcode == FUSE_MKDIR); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnImmediate([&](auto in __unused, auto& out) { + /* Let the killer proceed */ + sem_post(blocked_semaphore); + + /* Wait until after the signal has been sent */ + sem_wait(signaled_semaphore); + /* Allow time for the mkdir thread to receive the signal */ + nap(); + + /* Finally, complete the original op */ + SET_OUT_HEADER_LEN(out, entry); + out.body.create.entry.attr.mode = S_IFDIR | MODE; + out.body.create.entry.nodeid = ino; + }))); + EXPECT_CALL(*m_mock, process( + ResultOf([&](auto in) { + return (in.header.opcode == FUSE_INTERRUPT); + }, Eq(true)), + _) + ).Times(0); + + setup_interruptor(self); + ASSERT_EQ(0, mkdir(FULLDIRPATH0, MODE)) << strerror(errno); + + sem_destroy(&sem0); +} + /* FUSE_INTERRUPT operations should take priority over other pending ops */ -TEST_F(Interrupt, priority) +TEST_F(Intr, priority) { Sequence seq; uint64_t ino1 = 43; @@ -688,7 +745,7 @@ TEST_F(Interrupt, priority) * successfully interrupts the original */ /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ -TEST_F(Interrupt, too_soon) +TEST_F(Intr, too_soon) { Sequence seq; pthread_t self; diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc index f219cb3f95463..f992387d272e0 100644 --- a/tests/sys/fs/fusefs/mockfs.cc +++ b/tests/sys/fs/fusefs/mockfs.cc @@ -348,7 +348,7 @@ void MockFS::debug_response(const mockfs_buf_out &out) { MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions, bool push_symlinks_in, bool ro, enum poll_method pm, uint32_t flags, uint32_t kernel_minor_version, uint32_t max_write, bool async, - bool noclusterr, unsigned time_gran) + bool noclusterr, unsigned time_gran, bool nointr) { struct sigaction sa; struct iovec *iov = NULL; @@ -426,6 +426,13 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions, build_iovec(&iov, &iovlen, "noclusterr", __DECONST(void*, &trueval), sizeof(bool)); } + if (nointr) { + build_iovec(&iov, &iovlen, "nointr", + __DECONST(void*, &trueval), sizeof(bool)); + } else { + build_iovec(&iov, &iovlen, "intr", + __DECONST(void*, &trueval), sizeof(bool)); + } if (nmount(iov, iovlen, 0)) throw(std::system_error(errno, std::system_category(), "Couldn't mount filesystem")); diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh index 91bb248c6f809..ccf3d915bdb5f 100644 --- a/tests/sys/fs/fusefs/mockfs.hh +++ b/tests/sys/fs/fusefs/mockfs.hh @@ -323,7 +323,7 @@ class MockFS { bool default_permissions, bool push_symlinks_in, bool ro, enum poll_method pm, uint32_t flags, uint32_t kernel_minor_version, uint32_t max_write, bool async, - bool no_clusterr, unsigned time_gran); + bool no_clusterr, unsigned time_gran, bool nointr); virtual ~MockFS(); diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc index cca5d3582c2cc..c2451fc8bdc85 100644 --- a/tests/sys/fs/fusefs/utils.cc +++ b/tests/sys/fs/fusefs/utils.cc @@ -117,7 +117,8 @@ void FuseTest::SetUp() { m_mock = new MockFS(m_maxreadahead, m_allow_other, m_default_permissions, m_push_symlinks_in, m_ro, m_pm, m_init_flags, m_kernel_minor_version, - m_maxwrite, m_async, m_noclusterr, m_time_gran); + m_maxwrite, m_async, m_noclusterr, m_time_gran, + m_nointr); /* * FUSE_ACCESS is called almost universally. Expecting it in * each test case would be super-annoying. Instead, set a diff --git a/tests/sys/fs/fusefs/utils.hh b/tests/sys/fs/fusefs/utils.hh index 50b101e378c60..6fe870c091f68 100644 --- a/tests/sys/fs/fusefs/utils.hh +++ b/tests/sys/fs/fusefs/utils.hh @@ -57,6 +57,7 @@ class FuseTest : public ::testing::Test { bool m_ro; bool m_async; bool m_noclusterr; + bool m_nointr; unsigned m_time_gran; MockFS *m_mock = NULL; const static uint64_t FH = 0xdeadbeef1a7ebabe; @@ -77,6 +78,7 @@ class FuseTest : public ::testing::Test { m_ro(false), m_async(false), m_noclusterr(false), + m_nointr(false), m_time_gran(1) {} |
