Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Mar 2019 20:16:36 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r345201 - projects/fuse2/tests/sys/fs/fuse
Message-ID:  <201903152016.x2FKGaqb048685@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 */
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903152016.x2FKGaqb048685>