aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2019-07-18 17:55:13 +0000
committerAlan Somers <asomers@FreeBSD.org>2019-07-18 17:55:13 +0000
commited74f781c9f704092556f860a00b0bb53fdedff7 (patch)
treea0debdb972a97d02e135b2ba8ed5940f64fc87b2 /tests
parentf05962453e84168a0c0e616372bc99f10754a947 (diff)
Notes
Diffstat (limited to 'tests')
-rw-r--r--tests/sys/fs/fusefs/interrupt.cc75
-rw-r--r--tests/sys/fs/fusefs/mockfs.cc9
-rw-r--r--tests/sys/fs/fusefs/mockfs.hh2
-rw-r--r--tests/sys/fs/fusefs/utils.cc3
-rw-r--r--tests/sys/fs/fusefs/utils.hh2
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)
{}