svn commit: r345201 - projects/fuse2/tests/sys/fs/fuse
Alan Somers
asomers at FreeBSD.org
Fri Mar 15 20:16:37 UTC 2019
Author: asomers
Date: Fri Mar 15 20:16:35 2019
New Revision: 345201
URL: https://svnweb.freebsd.org/changeset/base/345201
Log:
fuse(4): add tests for the FUSE_ASYNC_READ option
Sponsored by: The FreeBSD Foundation
Modified:
projects/fuse2/tests/sys/fs/fuse/read.cc
Modified: projects/fuse2/tests/sys/fs/fuse/read.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/read.cc Fri Mar 15 18:59:04 2019 (r345200)
+++ projects/fuse2/tests/sys/fs/fuse/read.cc Fri Mar 15 20:16:35 2019 (r345201)
@@ -55,6 +55,7 @@ void expect_lookup(const char *relpath, uint64_t ino)
};
class AioRead: public Read {
+public:
virtual void SetUp() {
const char *node = "vfs.aio.enable_unsafe";
int val = 0;
@@ -69,6 +70,13 @@ virtual void SetUp() {
}
};
+class AsyncRead: public AioRead {
+ virtual void SetUp() {
+ m_init_flags = FUSE_ASYNC_READ;
+ AioRead::SetUp();
+ }
+};
+
class ReadAhead: public Read, public WithParamInterface<uint32_t> {
virtual void SetUp() {
m_maxreadahead = GetParam();
@@ -105,6 +113,159 @@ TEST_F(AioRead, aio_read)
ASSERT_EQ(0, aio_read(&iocb)) << strerror(errno);
ASSERT_EQ(bufsize, aio_waitcomplete(&piocb, NULL)) << strerror(errno);
ASSERT_EQ(0, memcmp(buf, CONTENTS, bufsize));
+ /* Deliberately leak fd. close(2) will be tested in release.cc */
+}
+
+/*
+ * Without the FUSE_ASYNC_READ mount option, fuse(4) should ensure that there
+ * is at most one outstanding read operation per file handle
+ */
+TEST_F(AioRead, async_read_disabled)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ uint64_t ino = 42;
+ int fd;
+ ssize_t bufsize = 50;
+ char buf0[bufsize], buf1[bufsize];
+ off_t off0 = 0;
+ off_t off1 = 4096;
+ struct aiocb iocb0, iocb1;
+
+ expect_lookup(RELPATH, ino);
+ expect_open(ino, 0, 1);
+ expect_getattr(ino, bufsize);
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([=](auto in) {
+ return (in->header.opcode == FUSE_READ &&
+ in->header.nodeid == ino &&
+ in->body.read.fh == FH &&
+ in->body.read.offset == (uint64_t)off0 &&
+ in->body.read.size == bufsize);
+ }, Eq(true)),
+ _)
+ ).WillOnce(Invoke([](auto in __unused, auto &out __unused) {
+ /* Filesystem is slow to respond */
+ }));
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([=](auto in) {
+ return (in->header.opcode == FUSE_READ &&
+ in->header.nodeid == ino &&
+ in->body.read.fh == FH &&
+ in->body.read.offset == (uint64_t)off1 &&
+ in->body.read.size == bufsize);
+ }, Eq(true)),
+ _)
+ ).Times(0);
+
+ fd = open(FULLPATH, O_RDONLY);
+ ASSERT_LE(0, fd) << strerror(errno);
+
+ /*
+ * Submit two AIO read requests, and respond to neither. If the
+ * filesystem ever gets the second read request, then we failed to
+ * limit outstanding reads.
+ */
+ iocb0.aio_nbytes = bufsize;
+ iocb0.aio_fildes = fd;
+ iocb0.aio_buf = buf0;
+ iocb0.aio_offset = off0;
+ iocb0.aio_sigevent.sigev_notify = SIGEV_NONE;
+ ASSERT_EQ(0, aio_read(&iocb0)) << strerror(errno);
+
+ iocb1.aio_nbytes = bufsize;
+ iocb1.aio_fildes = fd;
+ iocb1.aio_buf = buf1;
+ iocb1.aio_offset = off1;
+ iocb1.aio_sigevent.sigev_notify = SIGEV_NONE;
+ ASSERT_EQ(0, aio_read(&iocb1)) << strerror(errno);
+
+ /*
+ * Sleep for awhile to make sure the kernel has had a chance to issue
+ * the second read, even though the first has not yet returned
+ */
+ usleep(250'000);
+
+ /* Deliberately leak iocbs */
+ /* Deliberately leak fd. close(2) will be tested in release.cc */
+}
+
+/*
+ * With the FUSE_ASYNC_READ mount option, fuse(4) may issue multiple
+ * simultaneous read requests on the same file handle.
+ */
+/*
+ * Disabled because we don't yet implement FUSE_ASYNC_READ. No bugzilla
+ * entry, because that's a feature request, not a bug.
+ */
+TEST_F(AsyncRead, DISABLED_async_read)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ uint64_t ino = 42;
+ int fd;
+ ssize_t bufsize = 50;
+ char buf0[bufsize], buf1[bufsize];
+ off_t off0 = 0;
+ off_t off1 = 4096;
+ struct aiocb iocb0, iocb1;
+
+ expect_lookup(RELPATH, ino);
+ expect_open(ino, 0, 1);
+ expect_getattr(ino, bufsize);
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([=](auto in) {
+ return (in->header.opcode == FUSE_READ &&
+ in->header.nodeid == ino &&
+ in->body.read.fh == FH &&
+ in->body.read.offset == (uint64_t)off0 &&
+ in->body.read.size == bufsize);
+ }, Eq(true)),
+ _)
+ ).WillOnce(Invoke([](auto in __unused, auto &out __unused) {
+ /* Filesystem is slow to respond */
+ }));
+ EXPECT_CALL(*m_mock, process(
+ ResultOf([=](auto in) {
+ return (in->header.opcode == FUSE_READ &&
+ in->header.nodeid == ino &&
+ in->body.read.fh == FH &&
+ in->body.read.offset == (uint64_t)off1 &&
+ in->body.read.size == bufsize);
+ }, Eq(true)),
+ _)
+ ).WillOnce(Invoke([](auto in __unused, auto &out __unused) {
+ /* Filesystem is slow to respond */
+ }));
+
+ fd = open(FULLPATH, O_RDONLY);
+ ASSERT_LE(0, fd) << strerror(errno);
+
+ /*
+ * Submit two AIO read requests, but respond to neither. Ensure that
+ * we received both.
+ */
+ iocb0.aio_nbytes = bufsize;
+ iocb0.aio_fildes = fd;
+ iocb0.aio_buf = buf0;
+ iocb0.aio_offset = off0;
+ iocb0.aio_sigevent.sigev_notify = SIGEV_NONE;
+ ASSERT_EQ(0, aio_read(&iocb0)) << strerror(errno);
+
+ iocb1.aio_nbytes = bufsize;
+ iocb1.aio_fildes = fd;
+ iocb1.aio_buf = buf1;
+ iocb1.aio_offset = off1;
+ iocb1.aio_sigevent.sigev_notify = SIGEV_NONE;
+ ASSERT_EQ(0, aio_read(&iocb1)) << strerror(errno);
+
+ /*
+ * Sleep for awhile to make sure the kernel has had a chance to issue
+ * both reads.
+ */
+ usleep(250'000);
+
+ /* Deliberately leak iocbs */
/* Deliberately leak fd. close(2) will be tested in release.cc */
}
More information about the svn-src-projects
mailing list