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)
|
if (ioflag & IO_APPEND)
|
||||||
uio_setoffset(uio, filesize);
|
uio_setoffset(uio, filesize);
|
||||||
|
|
||||||
|
if (vn_rlimit_fsize(vp, uio, uio->uio_td))
|
||||||
|
return (EFBIG);
|
||||||
|
|
||||||
fdisp_init(&fdi, 0);
|
fdisp_init(&fdi, 0);
|
||||||
|
|
||||||
while (uio->uio_resid > 0) {
|
while (uio->uio_resid > 0) {
|
||||||
@ -579,6 +582,9 @@ fuse_write_biobackend(struct vnode *vp, struct uio *uio,
|
|||||||
if (ioflag & IO_APPEND)
|
if (ioflag & IO_APPEND)
|
||||||
uio_setoffset(uio, filesize);
|
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
|
* Find all of this file's B_NEEDCOMMIT buffers. If our writes
|
||||||
* would exceed the local maximum per-file write commit size when
|
* would exceed the local maximum per-file write commit size when
|
||||||
|
@ -31,12 +31,15 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#include <aio.h>
|
#include <aio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +51,22 @@ using namespace testing;
|
|||||||
class Write: public FuseTest {
|
class Write: public FuseTest {
|
||||||
|
|
||||||
public:
|
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)
|
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 {
|
class Write_7_8: public FuseTest {
|
||||||
|
|
||||||
public:
|
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 */
|
/* AIO writes need to set the header's pid field correctly */
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236379 */
|
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236379 */
|
||||||
TEST_F(AioWrite, DISABLED_aio_write)
|
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 */
|
/* 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
|
* 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
|
* write, then it must set the FUSE_WRITE_CACHE bit
|
||||||
|
Loading…
Reference in New Issue
Block a user