From nobody Wed Oct 12 04:50:02 2022 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 4MnKvZ5xj1z4fM7W; Wed, 12 Oct 2022 04:50:02 +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 4MnKvZ5VZqz3Bvj; Wed, 12 Oct 2022 04:50:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1665550202; 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=XBnCnEIXmJ+41ZyypLCgRnEHPCZpRPkr7gdFfLbMFsQ=; b=dYUez1P3QalVBwgtB3FnGxqxWs5Z7HnsHWSOVVc14/ORlrqfpnXi/RZw7ZzbA73c6BRSYC hITxKFVvWeUHdiN01XxTdlLF2pyAoNwTUtUWFxGw41IYVEmHiaF5jF7+hF+6rZ+D3t5duq f8Ad1BLHvxOLqcJPj98jrNjWsAw8FkuqB3ceWwXGGJLD9l0YQtzUqQ+oiTSkka0XkL9cZD DYPvJuAN5MnnNhpJnHll/GQl4XM9dhzcTsAFx9Y4hmGl8aqQZZbKGu+wRb/sYO0DvXzMvy 2MdDlUc6djmnW3wbVJQhNdsvrx8oLr/5gBUlENEhvQh2g704t3cLLm0ICuz15A== 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 4MnKvZ4K0Sz1C79; Wed, 12 Oct 2022 04:50:02 +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 29C4o2jK009799; Wed, 12 Oct 2022 04:50:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 29C4o28V009796; Wed, 12 Oct 2022 04:50:02 GMT (envelope-from git) Date: Wed, 12 Oct 2022 04:50:02 GMT Message-Id: <202210120450.29C4o28V009796@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: 0f0a0bdff052 - stable/13 - fusefs: truncate write if it would exceed RLIMIT_FSIZE 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: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: 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/13 X-Git-Reftype: branch X-Git-Commit: 0f0a0bdff052e4a61b20f6a0fc252e381c57c3ab Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1665550202; 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=XBnCnEIXmJ+41ZyypLCgRnEHPCZpRPkr7gdFfLbMFsQ=; b=S8cPdt6VaoegNRzQvuca8chABe6A2hvqvDLz/774dx3ncWi2WGfVZgNudwZcL9qyYu5gkH 58q5LS7R1sOWwM1yecf7/HMYyF863g107Y3C5MRPP1iAu0fMbAZ4LO/Alji24avfuxUiVy x/46kslBHhKBCyGOnANjUWqUYCzk/1D8DlWDL8isReXXjwkOdFkwL9eMqFXQV1qdewiYmY hmQ4Y3HBpQJh14T3z9FrNL4bDXVLB+gLBr1so0lhcZ34XSPaHNtHulIHAL8df7yFXRlQZy PYdooBimxKnI97v1W9ZFxtk1aBnZFNvHIeiEddclSzio4DcwFBIfKbLmp3PNEA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1665550202; a=rsa-sha256; cv=none; b=WYzKx5lfQxfOirzoP2TqjCHgy1AbBuVt9dd6usEa3/g1w0eBwh61ERzYYRwoIiwSZHD3Bv XOmT01KV39LiBjwDJXU/+CqPVl1gJQ2fYDZYH54zHdntcS12dR3/JEX6G2tvGlJZsos83q FeZh36Mkf/7yXU7NkaPuHkr4zgEElpA6eziAV8fR8hFxsAxEe4dnA/+PWfsgw2EKcNJXyc LZWVQgdb//X56mdea568cJupddQQtrt9IXg+LwwNUj8s8W/bQoIrFQ+8Yxkx/dz4LakRf1 ual7oOFDBXpNbRHZmQ/uoHDIAxnhTOHOJp6y9mzzbteWP2VSi8vTyitNmnR6jA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=0f0a0bdff052e4a61b20f6a0fc252e381c57c3ab commit 0f0a0bdff052e4a61b20f6a0fc252e381c57c3ab Author: Alan Somers AuthorDate: 2022-09-25 18:59:33 +0000 Commit: Alan Somers CommitDate: 2022-10-12 04:49:34 +0000 fusefs: truncate write if it would exceed RLIMIT_FSIZE PR: 164793 Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D36703 (cherry picked from commit be280f60dd8e8ef765a76966aac9c6ca7d6264d0) --- 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 179ee9e94f43..019093abf75a 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; @@ -723,6 +730,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.