summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAlan Somers <asomers@FreeBSD.org>2025-01-10 21:36:02 +0000
committerAlan Somers <asomers@FreeBSD.org>2025-04-17 20:14:58 +0000
commit1c316af141497cedb82971abddbbc53ea5264cef (patch)
tree9629d39456c0e0a0745bea70dc111df8957eaba7 /tests
parentd03aa29b82b803b440886a2f864dcdafa184c4fb (diff)
Diffstat (limited to 'tests')
-rw-r--r--tests/sys/fs/fusefs/mockfs.cc10
-rw-r--r--tests/sys/fs/fusefs/mockfs.hh8
-rw-r--r--tests/sys/fs/fusefs/read.cc53
-rw-r--r--tests/sys/fs/fusefs/utils.cc2
-rw-r--r--tests/sys/fs/fusefs/utils.hh2
5 files changed, 72 insertions, 3 deletions
diff --git a/tests/sys/fs/fusefs/mockfs.cc b/tests/sys/fs/fusefs/mockfs.cc
index 502f22a1e980..1fd2d5e358b1 100644
--- a/tests/sys/fs/fusefs/mockfs.cc
+++ b/tests/sys/fs/fusefs/mockfs.cc
@@ -416,7 +416,8 @@ void MockFS::debug_response(const mockfs_buf_out &out) {
}
}
-MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions,
+MockFS::MockFS(int max_read, 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 nointr, bool noatime,
@@ -424,6 +425,7 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions,
: m_daemon_id(NULL),
m_kernel_minor_version(kernel_minor_version),
m_kq(pm == KQ ? kqueue() : -1),
+ m_maxread(max_read),
m_maxreadahead(max_readahead),
m_pid(getpid()),
m_uniques(new std::unordered_set<uint64_t>),
@@ -470,6 +472,12 @@ MockFS::MockFS(int max_readahead, bool allow_other, bool default_permissions,
build_iovec(&iov, &iovlen, "from", __DECONST(void *, "/dev/fuse"), -1);
sprintf(fdstr, "%d", m_fuse_fd);
build_iovec(&iov, &iovlen, "fd", fdstr, -1);
+ if (m_maxread > 0) {
+ char val[10];
+
+ snprintf(val, sizeof(val), "%d", m_maxread);
+ build_iovec(&iov, &iovlen, "max_read=", &val, -1);
+ }
if (allow_other) {
build_iovec(&iov, &iovlen, "allow_other",
__DECONST(void*, &trueval), sizeof(bool));
diff --git a/tests/sys/fs/fusefs/mockfs.hh b/tests/sys/fs/fusefs/mockfs.hh
index 38efcd049a61..1de77767d0c9 100644
--- a/tests/sys/fs/fusefs/mockfs.hh
+++ b/tests/sys/fs/fusefs/mockfs.hh
@@ -294,6 +294,12 @@ class MockFS {
int m_kq;
+ /*
+ * If nonzero, the maximum size in bytes of a read that the kernel will
+ * send to the server.
+ */
+ int m_maxread;
+
/* The max_readahead file system option */
uint32_t m_maxreadahead;
@@ -355,7 +361,7 @@ class MockFS {
bool m_quit;
/* Create a new mockfs and mount it to a tempdir */
- MockFS(int max_readahead, bool allow_other,
+ MockFS(int max_read, 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,
diff --git a/tests/sys/fs/fusefs/read.cc b/tests/sys/fs/fusefs/read.cc
index 9693428914e6..e9c79ba2ffda 100644
--- a/tests/sys/fs/fusefs/read.cc
+++ b/tests/sys/fs/fusefs/read.cc
@@ -111,6 +111,13 @@ class ReadAhead: public Read,
}
};
+class ReadMaxRead: public Read {
+ virtual void SetUp() {
+ m_maxread = 16384;
+ Read::SetUp();
+ }
+};
+
class ReadNoatime: public Read {
virtual void SetUp() {
m_noatime = true;
@@ -840,6 +847,52 @@ TEST_F(Read, mmap)
leak(fd);
}
+
+/* When max_read is set, large reads will be split up as necessary */
+TEST_F(ReadMaxRead, split)
+{
+ const char FULLPATH[] = "mountpoint/some_file.txt";
+ const char RELPATH[] = "some_file.txt";
+ uint64_t ino = 42;
+ int fd;
+ ssize_t bufsize = 65536;
+ ssize_t fragsize = bufsize / 4;
+ char *rbuf, *frag0, *frag1, *frag2, *frag3;
+
+ rbuf = new char[bufsize]();
+ frag0 = new char[fragsize]();
+ frag1 = new char[fragsize]();
+ frag2 = new char[fragsize]();
+ frag3 = new char[fragsize]();
+ memset(frag0, '0', fragsize);
+ memset(frag1, '1', fragsize);
+ memset(frag2, '2', fragsize);
+ memset(frag3, '3', fragsize);
+
+ expect_lookup(RELPATH, ino, bufsize);
+ expect_open(ino, 0, 1);
+ expect_read(ino, 0, fragsize, fragsize, frag0);
+ expect_read(ino, fragsize, fragsize, fragsize, frag1);
+ expect_read(ino, 2 * fragsize, fragsize, fragsize, frag2);
+ expect_read(ino, 3 * fragsize, fragsize, fragsize, frag3);
+
+ fd = open(FULLPATH, O_RDONLY);
+ ASSERT_LE(0, fd) << strerror(errno);
+
+ ASSERT_EQ(bufsize, read(fd, rbuf, bufsize)) << strerror(errno);
+ ASSERT_EQ(0, memcmp(rbuf, frag0, fragsize));
+ ASSERT_EQ(0, memcmp(rbuf + fragsize, frag1, fragsize));
+ ASSERT_EQ(0, memcmp(rbuf + 2 * fragsize, frag2, fragsize));
+ ASSERT_EQ(0, memcmp(rbuf + 3 * fragsize, frag3, fragsize));
+
+ delete[] frag3;
+ delete[] frag2;
+ delete[] frag1;
+ delete[] frag0;
+ delete[] rbuf;
+ leak(fd);
+}
+
/*
* The kernel should not update the cached atime attribute during a read, if
* MNT_NOATIME is used.
diff --git a/tests/sys/fs/fusefs/utils.cc b/tests/sys/fs/fusefs/utils.cc
index 831ded0c0815..d059221b2e55 100644
--- a/tests/sys/fs/fusefs/utils.cc
+++ b/tests/sys/fs/fusefs/utils.cc
@@ -154,7 +154,7 @@ void FuseTest::SetUp() {
m_maxwrite = MIN(libfuse_max_write, (uint32_t)m_maxphys / 2);
try {
- m_mock = new MockFS(m_maxreadahead, m_allow_other,
+ m_mock = new MockFS(m_maxread, 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,
diff --git a/tests/sys/fs/fusefs/utils.hh b/tests/sys/fs/fusefs/utils.hh
index 506e8a985212..9dd8dad6b5cc 100644
--- a/tests/sys/fs/fusefs/utils.hh
+++ b/tests/sys/fs/fusefs/utils.hh
@@ -55,6 +55,7 @@ bool is_unsafe_aio_enabled(void);
extern const uint32_t libfuse_max_write;
class FuseTest : public ::testing::Test {
protected:
+ uint32_t m_maxread;
uint32_t m_maxreadahead;
uint32_t m_maxwrite;
uint32_t m_init_flags;
@@ -80,6 +81,7 @@ class FuseTest : public ::testing::Test {
unsigned long m_maxphys;
FuseTest():
+ m_maxread(0),
m_maxreadahead(0),
m_maxwrite(0),
m_init_flags(0),