From nobody Sun Sep 25 21:04:07 2022 X-Original-To: dev-commits-src-all@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 4MbJKM353Vz4cx89; Sun, 25 Sep 2022 21:04:07 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4MbJKM2gSKz3g2J; Sun, 25 Sep 2022 21:04:07 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1664139847; 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=cNoA+C16kv6ZgIlcFruaZwBBsO4l0kzcF6W9hD8eYrs=; b=YiZkpAPxQZlPZJ5EIUjao4i/KtXZs3ZH4CqZxCIG9pF8lYMCXPfHIowa5USK8udXL6iX4g ihtFeg6bAVTHXVqp0UyKk0AFiMQc7RZd0dkHHGVdK0OlT+phqXHoj+0dFtjxMwitZLo3BQ 8WGXY1wWsDTo07tdXQAXBSaMUddxTtkTl7aKDGHUTXWULBeD/lny4BbtPH5wb7A9rQ9leN 4V8AEQ0JXxD8FJ9CsJW3RYKmg/VKpnDPhjAAFgQG5ZRGy2wmXZ6BY1ZoqR7HYG9sNQP9aH 35ZQOO0MQnK+4UWzGMHwkeLgxzqCSCNCmJdI1HJVoURAxUkVDqh3kEvalBkmSg== 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 4MbJKM1gY4zYLb; Sun, 25 Sep 2022 21:04:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 28PL476c067059; Sun, 25 Sep 2022 21:04:07 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 28PL47L4067058; Sun, 25 Sep 2022 21:04:07 GMT (envelope-from git) Date: Sun, 25 Sep 2022 21:04:07 GMT Message-Id: <202209252104.28PL47L4067058@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: be280f60dd8e - main - fusefs: truncate write if it would exceed RLIMIT_FSIZE List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@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: be280f60dd8e8ef765a76966aac9c6ca7d6264d0 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1664139847; 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=cNoA+C16kv6ZgIlcFruaZwBBsO4l0kzcF6W9hD8eYrs=; b=qwya80tVjbA9cM+Orj4gfyvDv7uxOeWNJ6AZ0fcqaVJ/y8tEeEiI/H4ZzirSc8/kaBkeUJ gy3Mb1/xKdAHHGkdYkBLI6x5PwLcLUggAb/RlcpipGlUANou866t0G01XdnukzTW/4/Bmr ACmn8qOSzeG2kAJPQg3hbUQyhsS/6rkvFR9q0L6sJh/JFImKqE1s1vX7v8KDePEEw4Vo4p N/8+Vg+Q0r2xkzL0mtZZueY8S02lVH3T/gyih+v6wqx/e1epQ5i4C4+WeKc4tXSHkfsrtP 3U7TeT8VREKbH9i3oGZxqFmgu8WksrSLOsHz7kX7ZQRMIM/NL7++LdRaJmcQsw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1664139847; a=rsa-sha256; cv=none; b=pvQwa9xk5jGN9nIhyM3U2K/TSWlJolQMWC0K8skWoj/7/+e8NbcmVk8xpDDAgoVoCqkDW6 E6YhCvLSNhXaFSaGt6zcua/derrrkf7Fo3C54bBafqGWY/3RNluzeEUZXckSOTIMEAa8wM MZcqk25svh9t/VOscBiFOh9psrgHTDluf/x4Cgsqp++5YecJF7fX1GC6sJu/U1hhJh32qc JIubzW4Z6ZM0pf6WY9d7ff4gej1d/b0281crrEs9eiAM5heaIpB6pU44cb8tCJAVdDksrt QgKTBmGIFEjO/wulHKm2R3OZNn+QeDkc/PIksed6fMXTBnnTjArUxijPO9XxFw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=be280f60dd8e8ef765a76966aac9c6ca7d6264d0 commit be280f60dd8e8ef765a76966aac9c6ca7d6264d0 Author: Alan Somers AuthorDate: 2022-09-25 18:59:33 +0000 Commit: Alan Somers CommitDate: 2022-09-25 21:02:59 +0000 fusefs: truncate write if it would exceed RLIMIT_FSIZE PR: 164793 MFC after: 2 weeks Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D36703 --- sys/fs/fuse/fuse_io.c | 16 ++++++--- tests/sys/fs/fusefs/write.cc | 78 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 14 deletions(-) diff --git a/sys/fs/fuse/fuse_io.c b/sys/fs/fuse/fuse_io.c index 252fabb1c7d6..155406bc488f 100644 --- a/sys/fs/fuse/fuse_io.c +++ b/sys/fs/fuse/fuse_io.c @@ -303,6 +303,7 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio, struct fuse_write_out *fwo; struct fuse_dispatcher fdi; size_t chunksize; + ssize_t r; void *fwi_data; off_t as_written_offset; int diff; @@ -338,9 +339,11 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio, if (ioflag & IO_APPEND) uio_setoffset(uio, filesize); - err = vn_rlimit_fsize(vp, uio, uio->uio_td); - if (err != 0) + err = vn_rlimit_fsizex(vp, uio, 0, &r, uio->uio_td); + if (err != 0) { + vn_rlimit_fsizex_res(uio, r); return (err); + } fdisp_init(&fdi, 0); @@ -456,6 +459,7 @@ retry: if (wrote_anything) fuse_vnode_undirty_cached_timestamps(vp, false); + vn_rlimit_fsizex_res(uio, r); return (err); } @@ -472,6 +476,7 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio, struct buf *bp; daddr_t lbn; off_t filesize; + ssize_t r; int bcount; int n, on, seqcount, err = 0; @@ -494,9 +499,11 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio, if (ioflag & IO_APPEND) uio_setoffset(uio, filesize); - err = vn_rlimit_fsize(vp, uio, uio->uio_td); - if (err != 0) + err = vn_rlimit_fsizex(vp, uio, 0, &r, uio->uio_td); + if (err != 0) { + vn_rlimit_fsizex_res(uio, r); return (err); + } do { bool direct_append, extending; @@ -724,6 +731,7 @@ again: break; } while (uio->uio_resid > 0 && n > 0); + vn_rlimit_fsizex_res(uio, r); return (err); } diff --git a/tests/sys/fs/fusefs/write.cc b/tests/sys/fs/fusefs/write.cc index d685bd13aa17..4e76414a601a 100644 --- a/tests/sys/fs/fusefs/write.cc +++ b/tests/sys/fs/fusefs/write.cc @@ -52,10 +52,7 @@ using namespace testing; class Write: public FuseTest { public: -static sig_atomic_t s_sigxfsz; - void SetUp() { - s_sigxfsz = 0; FuseTest::SetUp(); } @@ -118,8 +115,6 @@ void maybe_expect_write(uint64_t ino, uint64_t offset, uint64_t size, }; -sig_atomic_t Write::s_sigxfsz = 0; - class Write_7_8: public FuseTest { public: @@ -211,8 +206,28 @@ virtual void SetUp() { class WriteEofDuringVnopStrategy: public Write, public WithParamInterface {}; +class WriteRlimitFsize: public Write, public WithParamInterface { +public: +static sig_atomic_t s_sigxfsz; +struct rlimit m_initial_limit; + +void SetUp() { + s_sigxfsz = 0; + getrlimit(RLIMIT_FSIZE, &m_initial_limit); + FuseTest::SetUp(); +} + +void TearDown() { + setrlimit(RLIMIT_FSIZE, &m_initial_limit); + + FuseTest::TearDown(); +} +}; + +sig_atomic_t WriteRlimitFsize::s_sigxfsz = 0; + void sigxfsz_handler(int __unused sig) { - Write::s_sigxfsz = 1; + WriteRlimitFsize::s_sigxfsz = 1; } /* AIO writes need to set the header's pid field correctly */ @@ -531,7 +546,7 @@ TEST_F(Write, direct_io_short_write_iov) } /* fusefs should respect RLIMIT_FSIZE */ -TEST_F(Write, rlimit_fsize) +TEST_P(WriteRlimitFsize, rlimit_fsize) { const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; @@ -540,17 +555,19 @@ TEST_F(Write, rlimit_fsize) ssize_t bufsize = strlen(CONTENTS); off_t offset = 1'000'000'000; uint64_t ino = 42; - int fd; + int fd, oflag; + + oflag = GetParam(); expect_lookup(RELPATH, ino, 0); expect_open(ino, 0, 1); rl.rlim_cur = offset; - rl.rlim_max = 10 * offset; + rl.rlim_max = m_initial_limit.rlim_max; ASSERT_EQ(0, setrlimit(RLIMIT_FSIZE, &rl)) << strerror(errno); ASSERT_NE(SIG_ERR, signal(SIGXFSZ, sigxfsz_handler)) << strerror(errno); - fd = open(FULLPATH, O_WRONLY); + fd = open(FULLPATH, O_WRONLY | oflag); ASSERT_LE(0, fd) << strerror(errno); @@ -560,6 +577,47 @@ TEST_F(Write, rlimit_fsize) leak(fd); } +/* + * When crossing the RLIMIT_FSIZE boundary, writes should be truncated, not + * aborted. + * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=164793 + */ +TEST_P(WriteRlimitFsize, rlimit_fsize_truncate) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefghijklmnopqrstuvwxyz"; + struct rlimit rl; + ssize_t bufsize = strlen(CONTENTS); + uint64_t ino = 42; + off_t offset = 1 << 30; + off_t limit = offset + strlen(CONTENTS) / 2; + int fd, oflag; + + oflag = GetParam(); + + expect_lookup(RELPATH, ino, 0); + expect_open(ino, 0, 1); + expect_write(ino, offset, bufsize / 2, bufsize / 2, CONTENTS); + + rl.rlim_cur = limit; + rl.rlim_max = m_initial_limit.rlim_max; + ASSERT_EQ(0, setrlimit(RLIMIT_FSIZE, &rl)) << strerror(errno); + ASSERT_NE(SIG_ERR, signal(SIGXFSZ, sigxfsz_handler)) << strerror(errno); + + fd = open(FULLPATH, O_WRONLY | oflag); + + ASSERT_LE(0, fd) << strerror(errno); + + ASSERT_EQ(bufsize / 2, pwrite(fd, CONTENTS, bufsize, offset)) + << strerror(errno); + leak(fd); +} + +INSTANTIATE_TEST_CASE_P(W, WriteRlimitFsize, + Values(0, O_DIRECT) +); + /* * A short read indicates EOF. Test that nothing bad happens if we get EOF * during the R of a RMW operation.