From nobody Wed Jan 15 20:31:18 2025 X-Original-To: dev-commits-src-main@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 4YYHhR0411z5kcY3; Wed, 15 Jan 2025 20:31:19 +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 "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YYHhQ6JLKz3ZBp; Wed, 15 Jan 2025 20:31:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1736973078; 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=wwG9Qvd7d81aV6bz7sM9Qk3+/SdxbS0yE6to5DEl37c=; b=k0rO38wF+995y9J7uNAlxEutAfWeNjIFuOVVKNVl+J+nwyra3FUUBzqiJOudiLQD+ArIDp NqOgEX1W8Mj4iRxHb3KLYWVcJDOl+VsslC159V6dhk43hCBSmKdrpTQz9pjy9gOkFozm/I 5uXZPOF/zzNOr+B1ULQV2PP5IhxWG6HPLYGY2TonERD/NVPmlh1OUCbgzJFNCj0wO67J2D CQXYyWK5sOnPu6hxherkqhkvnKBVMUJs8wWbIM/GsGui7KrmPstHlHRySrjlmutoLE8ndk 7PR8M7ttPgbQ0YjgO4Vf6wd36wqBotPlaFd7iDVTWsZT23pWIhEH5OUaZVGb4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1736973078; 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=wwG9Qvd7d81aV6bz7sM9Qk3+/SdxbS0yE6to5DEl37c=; b=O5UpRMqNzStwfxeoIof6YFx5CttdKSaRhmT3OH/1Zyoq+7xAPk7JREWGETVqHDL6IeFqMQ bk3THv5T3EA7yJiuSIA0kf3NrtQuUymQRki6MeZL5djUqghon4yzLr70t/in+a+IZojpWP zfddeyh8gITRo/jKXvuq/RitD5MuKUcSGXkwz+zEz0g9WEg85WFAoaowvpXftS7mcsdANV VTkIWj5/tKE9fesUn28EW0UpE/HcF8qdLxdEoVvcHpjNWao73HrEYfgW/Vn2tQESu7h28B 9/0hYnDei6fUvViDoDjPDwHS+KWdipfou4ga4yeT0J5gkpXac3IEYCNiLBtV7g== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1736973078; a=rsa-sha256; cv=none; b=BZVWuifU9BH3rKdlbQQJBKDBGT2+pSURgD9Q6EOKveBs5TdgIu/pRd2532mNvObbBffCKM dMgJe+25nDIT8sv/zVJpMeRLeHtC+nYt5U4zo51GNEfdAyOy+cT1BrXruAtQ8e+Z+n8pSt 0OHtyU4e8IyLa1BScQ3WDD88HfTvW9MSeGv/VG8I7UTu7J0zqyrvCSjZdvjCKWHWRLM43q 16TA2RnZmdIEm+DGJQksmb7g2B+znl+oLYUbTUbLbxN/oNRa8rwX6FPiz6bati/odROsSf WOhaV+IbLms8kzHCvnLWEgSo0KE3jjk8ZHMvJ5KaO2zwnswmmBDJwco2ka/jhw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none 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 4YYHhQ5qdsz11vG; Wed, 15 Jan 2025 20:31:18 +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 50FKVIIA065994; Wed, 15 Jan 2025 20:31:18 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 50FKVIHK065991; Wed, 15 Jan 2025 20:31:18 GMT (envelope-from git) Date: Wed, 15 Jan 2025 20:31:18 GMT Message-Id: <202501152031.50FKVIHK065991@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Alan Somers Subject: git: 9f31c4746041 - main - fusefs: add a test for the max_read= mount option List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@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/main X-Git-Reftype: branch X-Git-Commit: 9f31c47460412ab6ccae36a70ca019b47423ccec Auto-Submitted: auto-generated The branch main has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=9f31c47460412ab6ccae36a70ca019b47423ccec commit 9f31c47460412ab6ccae36a70ca019b47423ccec Author: Alan Somers AuthorDate: 2025-01-10 21:36:02 +0000 Commit: Alan Somers CommitDate: 2025-01-15 20:29:15 +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 --- 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),