fuse(4): add tests for the FUSE_ASYNC_READ option
Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
bce2c9bbd8
commit
48f58d58cf
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=345201
@ -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();
|
||||
@ -108,6 +116,159 @@ TEST_F(AioRead, aio_read)
|
||||
/* 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 */
|
||||
}
|
||||
|
||||
/* 0-length reads shouldn't cause any confusion */
|
||||
TEST_F(Read, direct_io_read_nothing)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user