fusefs: respect RLIMIT_FSIZE
Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
6ff7f297f8
commit
a639731ba9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=348593
@ -447,6 +447,9 @@ fuse_write_directbackend(struct vnode *vp, struct uio *uio,
|
||||
if (ioflag & IO_APPEND)
|
||||
uio_setoffset(uio, filesize);
|
||||
|
||||
if (vn_rlimit_fsize(vp, uio, uio->uio_td))
|
||||
return (EFBIG);
|
||||
|
||||
fdisp_init(&fdi, 0);
|
||||
|
||||
while (uio->uio_resid > 0) {
|
||||
@ -579,6 +582,9 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
||||
if (ioflag & IO_APPEND)
|
||||
uio_setoffset(uio, filesize);
|
||||
|
||||
if (vn_rlimit_fsize(vp, uio, uio->uio_td))
|
||||
return (EFBIG);
|
||||
|
||||
/*
|
||||
* Find all of this file's B_NEEDCOMMIT buffers. If our writes
|
||||
* would exceed the local maximum per-file write commit size when
|
||||
|
@ -31,12 +31,15 @@
|
||||
extern "C" {
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <aio.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
@ -48,6 +51,22 @@ using namespace testing;
|
||||
class Write: public FuseTest {
|
||||
|
||||
public:
|
||||
static sig_atomic_t s_sigxfsz;
|
||||
|
||||
void SetUp() {
|
||||
s_sigxfsz = 0;
|
||||
FuseTest::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() {
|
||||
struct sigaction sa;
|
||||
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGXFSZ, &sa, NULL);
|
||||
|
||||
FuseTest::TearDown();
|
||||
}
|
||||
|
||||
void expect_lookup(const char *relpath, uint64_t ino, uint64_t size)
|
||||
{
|
||||
@ -73,6 +92,8 @@ void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
|
||||
|
||||
};
|
||||
|
||||
sig_atomic_t Write::s_sigxfsz = 0;
|
||||
|
||||
class Write_7_8: public FuseTest {
|
||||
|
||||
public:
|
||||
@ -158,6 +179,10 @@ void expect_write(uint64_t ino, uint64_t offset, uint64_t isize,
|
||||
}
|
||||
};
|
||||
|
||||
void sigxfsz_handler(int __unused sig) {
|
||||
Write::s_sigxfsz = 1;
|
||||
}
|
||||
|
||||
/* AIO writes need to set the header's pid field correctly */
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236379 */
|
||||
TEST_F(AioWrite, DISABLED_aio_write)
|
||||
@ -372,6 +397,36 @@ TEST_F(Write, direct_io_short_write_iov)
|
||||
/* Deliberately leak fd. close(2) will be tested in release.cc */
|
||||
}
|
||||
|
||||
/* fusefs should respect RLIMIT_FSIZE */
|
||||
TEST_F(Write, rlimit_fsize)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
const char *CONTENTS = "abcdefgh";
|
||||
struct rlimit rl;
|
||||
ssize_t bufsize = strlen(CONTENTS);
|
||||
off_t offset = 1'000'000'000;
|
||||
uint64_t ino = 42;
|
||||
int fd;
|
||||
|
||||
expect_lookup(RELPATH, ino, 0);
|
||||
expect_open(ino, 0, 1);
|
||||
|
||||
rl.rlim_cur = offset;
|
||||
rl.rlim_max = 10 * offset;
|
||||
ASSERT_EQ(0, setrlimit(RLIMIT_FSIZE, &rl)) << strerror(errno);
|
||||
ASSERT_NE(SIG_ERR, signal(SIGXFSZ, sigxfsz_handler)) << strerror(errno);
|
||||
|
||||
fd = open(FULLPATH, O_WRONLY);
|
||||
|
||||
EXPECT_LE(0, fd) << strerror(errno);
|
||||
|
||||
ASSERT_EQ(-1, pwrite(fd, CONTENTS, bufsize, offset));
|
||||
EXPECT_EQ(EFBIG, errno);
|
||||
EXPECT_EQ(1, s_sigxfsz);
|
||||
/* Deliberately leak fd. close(2) will be tested in release.cc */
|
||||
}
|
||||
|
||||
/*
|
||||
* If the kernel cannot be sure which uid, gid, or pid was responsible for a
|
||||
* write, then it must set the FUSE_WRITE_CACHE bit
|
||||
|
Loading…
Reference in New Issue
Block a user