Date: Thu, 20 Jun 2019 12:11:48 -0600 From: Scott Long <scottl@samsco.org> To: Alan Somers <asomers@freebsd.org> Cc: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: Re: svn commit: r349238 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs Message-ID: <5E43BBD0-3308-4CDC-9E26-28AE496E8281@samsco.org> In-Reply-To: <201906201708.x5KH8M6e002674@repo.freebsd.org> References: <201906201708.x5KH8M6e002674@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
Great work! What happens if you set MAXPHYS to something big like 1MB? Scott > On Jun 20, 2019, at 11:08 AM, Alan Somers <asomers@freebsd.org> wrote: >=20 > Author: asomers > Date: Thu Jun 20 17:08:21 2019 > New Revision: 349238 > URL: https://svnweb.freebsd.org/changeset/base/349238 >=20 > Log: > fusefs: implement VOP_BMAP >=20 > If the fuse daemon supports FUSE_BMAP, then use that for the block = mapping. > Otherwise, use the same technique used by vop_stdbmap. Report large = values > for runp and runb in order to maximize read clustering and minimize = upcalls, > even if we don't know the true layout. >=20 > The major result of this change is that sequential reads to FUSE = files will > now usually happen 128KB at a time instead of 64KB. >=20 > Sponsored by: The FreeBSD Foundation >=20 > Added: > projects/fuse2/tests/sys/fs/fusefs/bmap.cc (contents, props = changed) > Modified: > projects/fuse2/sys/fs/fuse/fuse_internal.c > projects/fuse2/sys/fs/fuse/fuse_io.c > projects/fuse2/sys/fs/fuse/fuse_ipc.c > projects/fuse2/sys/fs/fuse/fuse_ipc.h > projects/fuse2/sys/fs/fuse/fuse_vnops.c > projects/fuse2/tests/sys/fs/fusefs/Makefile > projects/fuse2/tests/sys/fs/fusefs/mockfs.cc > projects/fuse2/tests/sys/fs/fusefs/mockfs.hh > projects/fuse2/tests/sys/fs/fusefs/read.cc > projects/fuse2/tests/sys/fs/fusefs/utils.cc >=20 > Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/sys/fs/fuse/fuse_internal.c Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/sys/fs/fuse/fuse_internal.c Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -908,7 +908,8 @@ fuse_internal_init_callback(struct fuse_ticket = *tick,=20 >=20 > if (fuse_libabi_geq(data, 7, 5)) { > if (fticket_resp(tick)->len =3D=3D sizeof(struct = fuse_init_out)) { > - data->max_readahead =3D fiio->max_readahead; > + data->max_readahead_blocks =3D = fiio->max_readahead / > + maxbcachebuf; > data->max_write =3D fiio->max_write; > if (fiio->flags & FUSE_ASYNC_READ) > data->dataflags |=3D FSESS_ASYNC_READ; >=20 > Modified: projects/fuse2/sys/fs/fuse/fuse_io.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/sys/fs/fuse/fuse_io.c Thu Jun 20 16:36:20 2019 = (r349237) > +++ projects/fuse2/sys/fs/fuse/fuse_io.c Thu Jun 20 17:08:21 2019 = (r349238) > @@ -321,10 +321,10 @@ fuse_read_biobackend(struct vnode *vp, struct = uio *uio > /* Try clustered read */ > long totread =3D uio->uio_resid + on; > seqcount =3D MIN(seqcount, > - data->max_readahead / biosize + 1); > + data->max_readahead_blocks + 1); > err =3D cluster_read(vp, filesize, lbn, bcount, = NOCRED, > totread, seqcount, 0, &bp); > - } else if (seqcount > 1 && data->max_readahead >=3D = nextsize) { > + } else if (seqcount > 1 && data->max_readahead_blocks >=3D= 1) { > /* Try non-clustered readahead */ > err =3D breadn(vp, lbn, bcount, &nextlbn, = &nextsize, 1, > NOCRED, &bp); >=20 > Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/sys/fs/fuse/fuse_ipc.c Thu Jun 20 16:36:20 2019 = (r349237) > +++ projects/fuse2/sys/fs/fuse/fuse_ipc.c Thu Jun 20 17:08:21 2019 = (r349238) > @@ -711,6 +711,10 @@ fuse_body_audit(struct fuse_ticket *ftick, size_t = blen > opcode =3D fticket_opcode(ftick); >=20 > switch (opcode) { > + case FUSE_BMAP: > + err =3D (blen =3D=3D sizeof(struct fuse_bmap_out)) ? 0 : = EINVAL; > + break; > + > case FUSE_LINK: > case FUSE_LOOKUP: > case FUSE_MKDIR: >=20 > Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.h > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/sys/fs/fuse/fuse_ipc.h Thu Jun 20 16:36:20 2019 = (r349237) > +++ projects/fuse2/sys/fs/fuse/fuse_ipc.h Thu Jun 20 17:08:21 2019 = (r349238) > @@ -197,7 +197,7 @@ struct fuse_data { > uint32_t fuse_libabi_major; > uint32_t fuse_libabi_minor; >=20 > - uint32_t max_readahead; > + uint32_t max_readahead_blocks; > uint32_t max_write; > uint32_t max_read; > uint32_t subtype; >=20 > Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/sys/fs/fuse/fuse_vnops.c Thu Jun 20 16:36:20 2019 = (r349237) > +++ projects/fuse2/sys/fs/fuse/fuse_vnops.c Thu Jun 20 17:08:21 2019 = (r349238) > @@ -120,6 +120,7 @@ SDT_PROBE_DEFINE2(fusefs, , vnops, trace, "int", = "char > /* vnode ops */ > static vop_access_t fuse_vnop_access; > static vop_advlock_t fuse_vnop_advlock; > +static vop_bmap_t fuse_vnop_bmap; > static vop_close_t fuse_fifo_close; > static vop_close_t fuse_vnop_close; > static vop_create_t fuse_vnop_create; > @@ -174,6 +175,7 @@ struct vop_vector fuse_vnops =3D { > .vop_default =3D &default_vnodeops, > .vop_access =3D fuse_vnop_access, > .vop_advlock =3D fuse_vnop_advlock, > + .vop_bmap =3D fuse_vnop_bmap, > .vop_close =3D fuse_vnop_close, > .vop_create =3D fuse_vnop_create, > .vop_deleteextattr =3D fuse_vnop_deleteextattr, > @@ -464,6 +466,92 @@ fuse_vnop_advlock(struct vop_advlock_args *ap) > } >=20 > return err; > +} > + > +/* { > + struct vnode *a_vp; > + daddr_t a_bn; > + struct bufobj **a_bop; > + daddr_t *a_bnp; > + int *a_runp; > + int *a_runb; > +} */ > +static int > +fuse_vnop_bmap(struct vop_bmap_args *ap) > +{ > + struct vnode *vp =3D ap->a_vp; > + struct bufobj **bo =3D ap->a_bop; > + struct thread *td =3D curthread; > + struct mount *mp; > + struct fuse_dispatcher fdi; > + struct fuse_bmap_in *fbi; > + struct fuse_bmap_out *fbo; > + struct fuse_data *data; > + uint64_t biosize; > + off_t filesize; > + daddr_t lbn =3D ap->a_bn; > + daddr_t *pbn =3D ap->a_bnp; > + int *runp =3D ap->a_runp; > + int *runb =3D ap->a_runb; > + int error =3D 0; > + int maxrun; > + > + if (fuse_isdeadfs(vp)) { > + return ENXIO; > + } > + > + mp =3D vnode_mount(vp); > + data =3D fuse_get_mpdata(mp); > + biosize =3D fuse_iosize(vp); > + maxrun =3D MIN(vp->v_mount->mnt_iosize_max / biosize - 1, > + data->max_readahead_blocks); > + > + if (bo !=3D NULL) > + *bo =3D &vp->v_bufobj; > + > + /* > + * The FUSE_BMAP operation does not include the runp and runb > + * variables, so we must guess. Report nonzero contiguous runs = so > + * cluster_read will combine adjacent reads. It's worthwhile to = reduce > + * upcalls even if we don't know the true physical layout of the = file. > + *=20 > + * FUSE file systems may opt out of read clustering in two ways: > + * * mounting with -onoclusterr > + * * Setting max_readahead <=3D maxbcachebuf during FUSE_INIT > + */ > + if (runb !=3D NULL) > + *runb =3D MIN(lbn, maxrun); > + if (runp !=3D NULL) { > + error =3D fuse_vnode_size(vp, &filesize, td->td_ucred, = td); > + if (error =3D=3D 0) > + *runp =3D MIN(MAX(0, filesize / biosize - lbn - = 1), > + maxrun); > + else > + *runp =3D 0; > + } > + > + if (fsess_isimpl(mp, FUSE_BMAP)) { > + fdisp_init(&fdi, sizeof(*fbi)); > + fdisp_make_vp(&fdi, FUSE_BMAP, vp, td, td->td_ucred); > + fbi =3D fdi.indata; > + fbi->block =3D lbn; > + fbi->blocksize =3D biosize; > + error =3D fdisp_wait_answ(&fdi); > + if (error =3D=3D ENOSYS) { > + fsess_set_notimpl(mp, FUSE_BMAP); > + error =3D 0; > + } else { > + fbo =3D fdi.answ; > + if (error =3D=3D 0 && pbn !=3D NULL) > + *pbn =3D fbo->block; > + return error; > + } > + } > + > + /* If the daemon doesn't support BMAP, make up a sensible = default */ > + if (pbn !=3D NULL) > + *pbn =3D lbn * btodb(biosize); > + return (error); > } >=20 > /* >=20 > Modified: projects/fuse2/tests/sys/fs/fusefs/Makefile > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/tests/sys/fs/fusefs/Makefile Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/tests/sys/fs/fusefs/Makefile Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -9,6 +9,7 @@ TESTSDIR=3D ${TESTSBASE}/sys/fs/fusefs > # out, so we get more granular reporting. > GTESTS+=3D access > GTESTS+=3D allow_other > +GTESTS+=3D bmap > GTESTS+=3D create > GTESTS+=3D default_permissions > GTESTS+=3D default_permissions_privileged >=20 > Added: projects/fuse2/tests/sys/fs/fusefs/bmap.cc > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- /dev/null 00:00:00 1970 (empty, because file is newly added) > +++ projects/fuse2/tests/sys/fs/fusefs/bmap.cc Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -0,0 +1,159 @@ > +/*- > + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD > + * > + * Copyright (c) 2019 The FreeBSD Foundation > + * > + * This software was developed by BFF Storage Systems, LLC under = sponsorship > + * from the FreeBSD Foundation. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above = copyright > + * notice, this list of conditions and the following disclaimer in = the > + * documentation and/or other materials provided with the = distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' = AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, = THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR = PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE = LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR = CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE = GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS = INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN = CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN = ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE = POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +extern "C" { > +#include <sys/param.h> > +#include <sys/ioctl.h> > +#include <sys/filio.h> > + > +#include <fcntl.h> > +} > + > +#include "mockfs.hh" > +#include "utils.hh" > + > +using namespace testing; > + > +const static char FULLPATH[] =3D "mountpoint/foo"; > +const static char RELPATH[] =3D "foo"; > + > +class Bmap: public FuseTest { > +public: > +virtual void SetUp() { > + m_maxreadahead =3D UINT32_MAX; > + FuseTest::SetUp(); > +} > +void expect_bmap(uint64_t ino, uint64_t lbn, uint32_t blocksize, = uint64_t pbn) > +{ > + EXPECT_CALL(*m_mock, process( > + ResultOf([=3D](auto in) { > + return (in.header.opcode =3D=3D FUSE_BMAP && > + in.header.nodeid =3D=3D ino && > + in.body.bmap.block =3D=3D lbn && > + in.body.bmap.blocksize =3D=3D = blocksize); > + }, Eq(true)), > + _) > + ).WillOnce(Invoke(ReturnImmediate([=3D](auto i __unused, auto& = out) { > + SET_OUT_HEADER_LEN(out, bmap); > + out.body.bmap.block =3D pbn; > + }))); > +} > +=09 > +void expect_lookup(const char *relpath, uint64_t ino, off_t size) > +{ > + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, size, 1, > + UINT64_MAX); > +} > +}; > + > +/* > + * Test FUSE_BMAP > + * XXX The FUSE protocol does not include the runp and runb = variables, so those > + * must be guessed in-kernel. > + */ > +TEST_F(Bmap, bmap) > +{ > + struct fiobmap2_arg arg; > + const off_t filesize =3D 1 << 20; > + const ino_t ino =3D 42; > + int64_t lbn =3D 10; > + int64_t pbn =3D 12345; > + int fd; > + > + expect_lookup(RELPATH, 42, filesize); > + expect_open(ino, 0, 1); > + expect_bmap(ino, lbn, m_maxbcachebuf, pbn); > + > + fd =3D open(FULLPATH, O_RDWR); > + ASSERT_LE(0, fd) << strerror(errno); > + > + arg.bn =3D lbn; > + arg.runp =3D -1; > + arg.runb =3D -1; > + ASSERT_EQ(0, ioctl(fd, FIOBMAP2, &arg)) << strerror(errno); > + EXPECT_EQ(arg.bn, pbn); > + EXPECT_EQ(arg.runp, MAXPHYS / m_maxbcachebuf - 1); > + EXPECT_EQ(arg.runb, MAXPHYS / m_maxbcachebuf - 1); > +} > + > +/*=20 > + * If the daemon does not implement VOP_BMAP, fusefs should return = sensible > + * defaults. > + */ > +TEST_F(Bmap, default_) > +{ > + struct fiobmap2_arg arg; > + const off_t filesize =3D 1 << 20; > + const ino_t ino =3D 42; > + int64_t lbn; > + int fd; > + > + expect_lookup(RELPATH, 42, filesize); > + expect_open(ino, 0, 1); > + EXPECT_CALL(*m_mock, process( > + ResultOf([=3D](auto in) { > + return (in.header.opcode =3D=3D FUSE_BMAP); > + }, Eq(true)), > + _) > + ).WillOnce(Invoke(ReturnErrno(ENOSYS))); > + > + fd =3D open(FULLPATH, O_RDWR); > + ASSERT_LE(0, fd) << strerror(errno); > + > + /* First block */ > + lbn =3D 0; > + arg.bn =3D lbn; > + arg.runp =3D -1; > + arg.runb =3D -1; > + ASSERT_EQ(0, ioctl(fd, FIOBMAP2, &arg)) << strerror(errno); > + EXPECT_EQ(arg.bn, 0); > + EXPECT_EQ(arg.runp, MAXPHYS / m_maxbcachebuf - 1); > + EXPECT_EQ(arg.runb, 0); > + > + /* In the middle */ > + lbn =3D filesize / m_maxbcachebuf / 2; > + arg.bn =3D lbn; > + arg.runp =3D -1; > + arg.runb =3D -1; > + ASSERT_EQ(0, ioctl(fd, FIOBMAP2, &arg)) << strerror(errno); > + EXPECT_EQ(arg.bn, lbn * m_maxbcachebuf / DEV_BSIZE); > + EXPECT_EQ(arg.runp, MAXPHYS / m_maxbcachebuf - 1); > + EXPECT_EQ(arg.runb, MAXPHYS / m_maxbcachebuf - 1); > + > + /* Last block */ > + lbn =3D filesize / m_maxbcachebuf - 1; > + arg.bn =3D lbn; > + arg.runp =3D -1; > + arg.runb =3D -1; > + ASSERT_EQ(0, ioctl(fd, FIOBMAP2, &arg)) << strerror(errno); > + EXPECT_EQ(arg.bn, lbn * m_maxbcachebuf / DEV_BSIZE); > + EXPECT_EQ(arg.runp, 0); > + EXPECT_EQ(arg.runb, MAXPHYS / m_maxbcachebuf - 1); > +} >=20 > Modified: projects/fuse2/tests/sys/fs/fusefs/mockfs.cc > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/tests/sys/fs/fusefs/mockfs.cc Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/tests/sys/fs/fusefs/mockfs.cc Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -168,6 +168,10 @@ void MockFS::debug_request(const mockfs_buf_in = &in) > case FUSE_ACCESS: > printf(" mask=3D%#x", in.body.access.mask); > break; > + case FUSE_BMAP: > + printf(" block=3D%#lx blocksize=3D%#x", = in.body.bmap.block, > + in.body.bmap.blocksize); > + break; > case FUSE_CREATE: > if (m_kernel_minor_version >=3D 12) > name =3D (const char*)in.body.bytes + >=20 > Modified: projects/fuse2/tests/sys/fs/fusefs/mockfs.hh > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/tests/sys/fs/fusefs/mockfs.hh Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/tests/sys/fs/fusefs/mockfs.hh Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -124,6 +124,7 @@ struct fuse_create_out_7_8 { >=20 > union fuse_payloads_in { > fuse_access_in access; > + fuse_bmap_in bmap; > /* value is from fuse_kern_chan.c in fusefs-libs */ > uint8_t bytes[0x21000 - sizeof(struct fuse_in_header)]; > fuse_create_in create; > @@ -164,6 +165,7 @@ struct mockfs_buf_in { > union fuse_payloads_out { > fuse_attr_out attr; > fuse_attr_out_7_8 attr_7_8; > + fuse_bmap_out bmap; > fuse_create_out create; > fuse_create_out_7_8 create_7_8; > /* >=20 > Modified: projects/fuse2/tests/sys/fs/fusefs/read.cc > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/tests/sys/fs/fusefs/read.cc Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/tests/sys/fs/fusefs/read.cc Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -29,7 +29,7 @@ > */ >=20 > extern "C" { > -#include <sys/types.h> > +#include <sys/param.h> > #include <sys/mman.h> > #include <sys/socket.h> > #include <sys/sysctl.h> > @@ -749,16 +749,15 @@ TEST_F(ReadCacheable, DISABLED_sendfile_eio) > /* Deliberately leak fd. close(2) will be tested in release.cc = */ > } >=20 > -/* Large reads should be clustered, even across cache block = boundaries */ > -/*=20 > - * Disabled because clustered reads requires VOP_BMAP, which fusefs = does not > - * yet support > +/* > + * Sequential reads should use readahead. And if allowed, large = reads should > + * be clustered. > */ > -TEST_P(ReadAhead, DISABLED_cluster) { > +TEST_P(ReadAhead, readahead) { > const char FULLPATH[] =3D "mountpoint/some_file.txt"; > const char RELPATH[] =3D "some_file.txt"; > uint64_t ino =3D 42; > - int fd, maxcontig; > + int fd, maxcontig, clustersize; > ssize_t bufsize =3D 4 * m_maxbcachebuf; > ssize_t filesize =3D bufsize; > uint64_t len; > @@ -774,8 +773,9 @@ TEST_P(ReadAhead, DISABLED_cluster) { > expect_open(ino, 0, 1); > maxcontig =3D m_noclusterr ? m_maxbcachebuf : > m_maxbcachebuf + = (int)get<1>(GetParam()); > - for (offs =3D 0; offs < bufsize; offs +=3D maxcontig) { > - len =3D std::min((size_t)maxcontig, (size_t)(filesize - = offs)); > + clustersize =3D MIN(maxcontig, MAXPHYS); > + for (offs =3D 0; offs < bufsize; offs +=3D clustersize) { > + len =3D std::min((size_t)clustersize, (size_t)(filesize = - offs)); > expect_read(ino, offs, len, len, contents + offs); > } >=20 > @@ -791,47 +791,11 @@ TEST_P(ReadAhead, DISABLED_cluster) { > /* Deliberately leak fd. close(2) will be tested in release.cc = */ > } >=20 > -/* fuse(4) should honor the filesystem's requested m_readahead = parameter */ > -TEST_P(ReadAhead, readahead) { > - const char FULLPATH[] =3D "mountpoint/some_file.txt"; > - const char RELPATH[] =3D "some_file.txt"; > - uint64_t ino =3D 42; > - int fd, i; > - ssize_t bufsize =3D m_maxbcachebuf; > - ssize_t filesize =3D m_maxbcachebuf * 6; > - char *rbuf, *contents; > - > - contents =3D (char*)malloc(filesize); > - ASSERT_NE(NULL, contents); > - memset(contents, 'X', filesize); > - rbuf =3D (char*)calloc(1, bufsize); > - > - expect_lookup(RELPATH, ino, filesize); > - expect_open(ino, 0, 1); > - /* fuse(4) should only read ahead the allowed amount */ > - expect_read(ino, 0, m_maxbcachebuf, m_maxbcachebuf, contents); > - for (i =3D 0; i < (int)get<1>(GetParam()) / m_maxbcachebuf; i++) = { > - off_t offs =3D (i + 1) * m_maxbcachebuf; > - expect_read(ino, offs, m_maxbcachebuf, m_maxbcachebuf, > - contents + offs); > - } > - > - fd =3D open(FULLPATH, O_RDONLY); > - ASSERT_LE(0, fd) << strerror(errno); > - > - /* Set the internal readahead counter to a "large" value */ > - ASSERT_EQ(0, fcntl(fd, F_READAHEAD, 1'000'000'000)) << = strerror(errno); > - > - ASSERT_EQ(bufsize, read(fd, rbuf, bufsize)) << strerror(errno); > - ASSERT_EQ(0, memcmp(rbuf, contents, bufsize)); > - > - /* Deliberately leak fd. close(2) will be tested in release.cc = */ > -} > - > INSTANTIATE_TEST_CASE_P(RA, ReadAhead, > Values(tuple<bool, int>(false, 0u), > tuple<bool, int>(false, 0x10000), > tuple<bool, int>(false, 0x20000), > tuple<bool, int>(false, 0x30000), > tuple<bool, int>(true, 0u), > - tuple<bool, int>(true, 0x10000))); > + tuple<bool, int>(true, 0x10000), > + tuple<bool, int>(true, 0x20000))); >=20 > Modified: projects/fuse2/tests/sys/fs/fusefs/utils.cc > = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D > --- projects/fuse2/tests/sys/fs/fusefs/utils.cc Thu Jun 20 = 16:36:20 2019 (r349237) > +++ projects/fuse2/tests/sys/fs/fusefs/utils.cc Thu Jun 20 = 17:08:21 2019 (r349238) > @@ -129,6 +129,20 @@ void FuseTest::SetUp() { > _) > ).Times(AnyNumber()) > .WillRepeatedly(Invoke(ReturnErrno(ENOSYS))); > + /* > + * FUSE_BMAP is called for most test cases that read = data. Set > + * a default expectation and return ENOSYS. > + * > + * Individual test cases can override this expectation = since > + * googlemock evaluates expectations in LIFO order. > + */ > + EXPECT_CALL(*m_mock, process( > + ResultOf([=3D](auto in) { > + return (in.header.opcode =3D=3D = FUSE_BMAP); > + }, Eq(true)), > + _) > + ).Times(AnyNumber()) > + .WillRepeatedly(Invoke(ReturnErrno(ENOSYS))); > } catch (std::system_error err) { > FAIL() << err.what(); > } >=20
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?5E43BBD0-3308-4CDC-9E26-28AE496E8281>