From nobody Thu Apr 17 23:37:43 2025 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ZdvT33VDmz5sytC; Thu, 17 Apr 2025 23:37:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZdvT32G5Tz3QBX; Thu, 17 Apr 2025 23:37:43 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744933063; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=plT4qxToUw+7YSx3HCp5CMUt0zf82yMhB46ynZqIzwU=; b=LD6mAHyQmRd970S9HQncDtYI/M9CmFhDifqsTj0nzYypDsWkpnFMiWAn66HGQyIfJ39Ium EqBUkW91yXSdAAWpnaRUZ7mLf4leUrDnQr2+QiLw/LvJvgDgrvzu6ukLh2ccPGySszsyW2 ZrRDVdtoz/GL/cIKKZFJlhE/KK/eXySx5HA2uW8JUwwrcYFOMRG0/dnSU8qI9mI+oKLoej nCVw81um+EyeGFHbbmphK9Ef6hbyn4DZ5B7SoY7DI3UzKUUMCNyrQD2T31RgN3aNm6JVX2 wWq/XKXbXlUszt6No2q3Y30UZFGDMleUve9KpLHDes0V1hFc050whR3eAiBH2Q== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1744933063; a=rsa-sha256; cv=none; b=M12IMfyJBOdmNtbUN8ihDauZtrYZNR8+/c7X/IhegH9w1iL3zye0tqbmsxxcr7vXwig/zH q3Oop+H+LoSwps5BhxOO0/6d455AWT4KqIPdGdOLs6H5HHijz9AbKJhx47MOMU++1+AoYH K21zawMtuf4rFIcxG8gtz5382WZOzFZOFZo/lm3xMD1eyCNA9Y2NkrlQtoCxGfMDIoGJ1U pWh1Ti0vgTXDZYLx4+gNTvAt09HMRr/PHy3pDWjaxeRK/t7YIpvC5UEQFwoxg0hpkjM2pj X8sbzD8BYehHq8T9kqrQLkSGJFbmf0gT86tYOZ1TDFYOrE6mr4zeKUiCyL+1eA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1744933063; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=plT4qxToUw+7YSx3HCp5CMUt0zf82yMhB46ynZqIzwU=; b=aiBpe42IDYaQruJrCJx7/4WSN0J/gmJ04DtnTogpyWuYKx94gqgqGBzEQ7b2ecJl01ICia uufp/6QlciXNJW0jNEKrQgeZ90ainHlOuftCm7UcCwR2C6pz6wYW+gA00/j83wsVNZlKai VtIVDX6fI8kVs+NjCLHbiTC9H5y6gzaqEOET34K9A9RAEHLpANFn5ep7BJz6B9XqfuOMpN dOkd4s6ZqySTRDWXavVpPD/NuIABaOqw7RhgqknlO/OQqDvhZd5SrHdkBWCb8BTLfiyrhS lcGQ/O5kmpuxI8YWhuYexvFR0uLht12Gdt4qMwb+4Pboi/sCgIUqECu55UELow== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZdvT31h0Dz17s2; Thu, 17 Apr 2025 23:37:43 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 53HNbhEH089394; Thu, 17 Apr 2025 23:37:43 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 53HNbh3h089391; Thu, 17 Apr 2025 23:37:43 GMT (envelope-from git) Date: Thu, 17 Apr 2025 23:37:43 GMT Message-Id: <202504172337.53HNbh3h089391@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Alan Somers Subject: git: 1c316af14149 - stable/14 - fusefs: add a test for the max_read= mount option List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: asomers X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 1c316af141497cedb82971abddbbc53ea5264cef Auto-Submitted: auto-generated The branch stable/14 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=1c316af141497cedb82971abddbbc53ea5264cef commit 1c316af141497cedb82971abddbbc53ea5264cef Author: Alan Somers AuthorDate: 2025-01-10 21:36:02 +0000 Commit: Alan Somers CommitDate: 2025-04-17 20:14:58 +0000 fusefs: add a test for the max_read= mount option When set, this limits the amount of data that the kernel will request of the server in any single read operation. The option has always been available in our fusefs implementation, but never covered by the test suite. MFC after: 2 weeks Sponsored by: ConnectWise (cherry picked from commit 9f31c47460412ab6ccae36a70ca019b47423ccec) --- tests/sys/fs/fusefs/mockfs.cc | 10 +++++++- tests/sys/fs/fusefs/mockfs.hh | 8 ++++++- tests/sys/fs/fusefs/read.cc | 53 +++++++++++++++++++++++++++++++++++++++++++ tests/sys/fs/fusefs/utils.cc | 2 +- tests/sys/fs/fusefs/utils.hh | 2 ++ 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), @@ -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),