svn commit: r349238 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs

Scott Long scottl at samsco.org
Thu Jun 20 18:11:58 UTC 2019


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 at freebsd.org> wrote:
> 
> Author: asomers
> Date: Thu Jun 20 17:08:21 2019
> New Revision: 349238
> URL: https://svnweb.freebsd.org/changeset/base/349238
> 
> Log:
>  fusefs: implement VOP_BMAP
> 
>  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.
> 
>  The major result of this change is that sequential reads to FUSE files will
>  now usually happen 128KB at a time instead of 64KB.
> 
>  Sponsored by:	The FreeBSD Foundation
> 
> 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
> 
> Modified: projects/fuse2/sys/fs/fuse/fuse_internal.c
> ==============================================================================
> --- 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, 
> 
> 	if (fuse_libabi_geq(data, 7, 5)) {
> 		if (fticket_resp(tick)->len == sizeof(struct fuse_init_out)) {
> -			data->max_readahead = fiio->max_readahead;
> +			data->max_readahead_blocks = fiio->max_readahead /
> +				maxbcachebuf;
> 			data->max_write = fiio->max_write;
> 			if (fiio->flags & FUSE_ASYNC_READ)
> 				data->dataflags |= FSESS_ASYNC_READ;
> 
> Modified: projects/fuse2/sys/fs/fuse/fuse_io.c
> ==============================================================================
> --- 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 = uio->uio_resid + on;
> 			seqcount = MIN(seqcount,
> -				data->max_readahead / biosize + 1);
> +				data->max_readahead_blocks + 1);
> 			err = cluster_read(vp, filesize, lbn, bcount, NOCRED,
> 				totread, seqcount, 0, &bp);
> -		} else if (seqcount > 1 && data->max_readahead >= nextsize) {
> +		} else if (seqcount > 1 && data->max_readahead_blocks >= 1) {
> 			/* Try non-clustered readahead */
> 			err = breadn(vp, lbn, bcount, &nextlbn, &nextsize, 1,
> 				NOCRED, &bp);
> 
> Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.c
> ==============================================================================
> --- 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 = fticket_opcode(ftick);
> 
> 	switch (opcode) {
> +	case FUSE_BMAP:
> +		err = (blen == sizeof(struct fuse_bmap_out)) ? 0 : EINVAL;
> +		break;
> +
> 	case FUSE_LINK:
> 	case FUSE_LOOKUP:
> 	case FUSE_MKDIR:
> 
> Modified: projects/fuse2/sys/fs/fuse/fuse_ipc.h
> ==============================================================================
> --- 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;
> 
> -	uint32_t			max_readahead;
> +	uint32_t			max_readahead_blocks;
> 	uint32_t			max_write;
> 	uint32_t			max_read;
> 	uint32_t			subtype;
> 
> Modified: projects/fuse2/sys/fs/fuse/fuse_vnops.c
> ==============================================================================
> --- 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 = {
> 	.vop_default = &default_vnodeops,
> 	.vop_access = fuse_vnop_access,
> 	.vop_advlock = fuse_vnop_advlock,
> +	.vop_bmap = fuse_vnop_bmap,
> 	.vop_close = fuse_vnop_close,
> 	.vop_create = fuse_vnop_create,
> 	.vop_deleteextattr = fuse_vnop_deleteextattr,
> @@ -464,6 +466,92 @@ fuse_vnop_advlock(struct vop_advlock_args *ap)
> 	}
> 
> 	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 = ap->a_vp;
> +	struct bufobj **bo = ap->a_bop;
> +	struct thread *td = 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 = ap->a_bn;
> +	daddr_t *pbn = ap->a_bnp;
> +	int *runp = ap->a_runp;
> +	int *runb = ap->a_runb;
> +	int error = 0;
> +	int maxrun;
> +
> +	if (fuse_isdeadfs(vp)) {
> +		return ENXIO;
> +	}
> +
> +	mp = vnode_mount(vp);
> +	data = fuse_get_mpdata(mp);
> +	biosize = fuse_iosize(vp);
> +	maxrun = MIN(vp->v_mount->mnt_iosize_max / biosize - 1,
> +		data->max_readahead_blocks);
> +
> +	if (bo != NULL)
> +		*bo = &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.
> +	 * 
> +	 * FUSE file systems may opt out of read clustering in two ways:
> +	 * * mounting with -onoclusterr
> +	 * * Setting max_readahead <= maxbcachebuf during FUSE_INIT
> +	 */
> +	if (runb != NULL)
> +		*runb = MIN(lbn, maxrun);
> +	if (runp != NULL) {
> +		error = fuse_vnode_size(vp, &filesize, td->td_ucred, td);
> +		if (error == 0)
> +			*runp = MIN(MAX(0, filesize / biosize - lbn - 1),
> +				    maxrun);
> +		else
> +			*runp = 0;
> +	}
> +
> +	if (fsess_isimpl(mp, FUSE_BMAP)) {
> +		fdisp_init(&fdi, sizeof(*fbi));
> +		fdisp_make_vp(&fdi, FUSE_BMAP, vp, td, td->td_ucred);
> +		fbi = fdi.indata;
> +		fbi->block = lbn;
> +		fbi->blocksize = biosize;
> +		error = fdisp_wait_answ(&fdi);
> +		if (error == ENOSYS) {
> +			fsess_set_notimpl(mp, FUSE_BMAP);
> +			error = 0;
> +		} else {
> +			fbo = fdi.answ;
> +			if (error == 0 && pbn != NULL)
> +				*pbn = fbo->block;
> +			return error;
> +		}
> +	}
> +
> +	/* If the daemon doesn't support BMAP, make up a sensible default */
> +	if (pbn != NULL)
> +		*pbn = lbn * btodb(biosize);
> +	return (error);
> }
> 
> /*
> 
> Modified: projects/fuse2/tests/sys/fs/fusefs/Makefile
> ==============================================================================
> --- 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=	${TESTSBASE}/sys/fs/fusefs
> # out, so we get more granular reporting.
> GTESTS+=	access
> GTESTS+=	allow_other
> +GTESTS+=	bmap
> GTESTS+=	create
> GTESTS+=	default_permissions
> GTESTS+=	default_permissions_privileged
> 
> Added: projects/fuse2/tests/sys/fs/fusefs/bmap.cc
> ==============================================================================
> --- /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[] = "mountpoint/foo";
> +const static char RELPATH[] = "foo";
> +
> +class Bmap: public FuseTest {
> +public:
> +virtual void SetUp() {
> +	m_maxreadahead = 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([=](auto in) {
> +			return (in.header.opcode == FUSE_BMAP &&
> +				in.header.nodeid == ino &&
> +				in.body.bmap.block == lbn &&
> +				in.body.bmap.blocksize == blocksize);
> +		}, Eq(true)),
> +		_)
> +	).WillOnce(Invoke(ReturnImmediate([=](auto i __unused, auto& out) {
> +		SET_OUT_HEADER_LEN(out, bmap);
> +		out.body.bmap.block = pbn;
> +	})));
> +}
> +	
> +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 = 1 << 20;
> +	const ino_t ino = 42;
> +	int64_t lbn = 10;
> +	int64_t pbn = 12345;
> +	int fd;
> +
> +	expect_lookup(RELPATH, 42, filesize);
> +	expect_open(ino, 0, 1);
> +	expect_bmap(ino, lbn, m_maxbcachebuf, pbn);
> +
> +	fd = open(FULLPATH, O_RDWR);
> +	ASSERT_LE(0, fd) << strerror(errno);
> +
> +	arg.bn = lbn;
> +	arg.runp = -1;
> +	arg.runb = -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);
> +}
> +
> +/* 
> + * 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 = 1 << 20;
> +	const ino_t ino = 42;
> +	int64_t lbn;
> +	int fd;
> +
> +	expect_lookup(RELPATH, 42, filesize);
> +	expect_open(ino, 0, 1);
> +	EXPECT_CALL(*m_mock, process(
> +		ResultOf([=](auto in) {
> +			return (in.header.opcode == FUSE_BMAP);
> +		}, Eq(true)),
> +		_)
> +	).WillOnce(Invoke(ReturnErrno(ENOSYS)));
> +
> +	fd = open(FULLPATH, O_RDWR);
> +	ASSERT_LE(0, fd) << strerror(errno);
> +
> +	/* First block */
> +	lbn = 0;
> +	arg.bn = lbn;
> +	arg.runp = -1;
> +	arg.runb = -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 = filesize / m_maxbcachebuf / 2;
> +	arg.bn = lbn;
> +	arg.runp = -1;
> +	arg.runb = -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 = filesize / m_maxbcachebuf - 1;
> +	arg.bn = lbn;
> +	arg.runp = -1;
> +	arg.runb = -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);
> +}
> 
> Modified: projects/fuse2/tests/sys/fs/fusefs/mockfs.cc
> ==============================================================================
> --- 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=%#x", in.body.access.mask);
> 			break;
> +		case FUSE_BMAP:
> +			printf(" block=%#lx blocksize=%#x", in.body.bmap.block,
> +				in.body.bmap.blocksize);
> +			break;
> 		case FUSE_CREATE:
> 			if (m_kernel_minor_version >= 12)
> 				name = (const char*)in.body.bytes +
> 
> Modified: projects/fuse2/tests/sys/fs/fusefs/mockfs.hh
> ==============================================================================
> --- 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 {
> 
> 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;
> 	/*
> 
> Modified: projects/fuse2/tests/sys/fs/fusefs/read.cc
> ==============================================================================
> --- 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 @@
>  */
> 
> 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 */
> }
> 
> -/* Large reads should be clustered, even across cache block boundaries */
> -/* 
> - * 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[] = "mountpoint/some_file.txt";
> 	const char RELPATH[] = "some_file.txt";
> 	uint64_t ino = 42;
> -	int fd, maxcontig;
> +	int fd, maxcontig, clustersize;
> 	ssize_t bufsize = 4 * m_maxbcachebuf;
> 	ssize_t filesize = bufsize;
> 	uint64_t len;
> @@ -774,8 +773,9 @@ TEST_P(ReadAhead, DISABLED_cluster) {
> 	expect_open(ino, 0, 1);
> 	maxcontig = m_noclusterr ? m_maxbcachebuf :
> 				   m_maxbcachebuf + (int)get<1>(GetParam());
> -	for (offs = 0; offs < bufsize; offs += maxcontig) {
> -		len = std::min((size_t)maxcontig, (size_t)(filesize - offs));
> +	clustersize = MIN(maxcontig, MAXPHYS);
> +	for (offs = 0; offs < bufsize; offs += clustersize) {
> +		len = std::min((size_t)clustersize, (size_t)(filesize - offs));
> 		expect_read(ino, offs, len, len, contents + offs);
> 	}
> 
> @@ -791,47 +791,11 @@ TEST_P(ReadAhead, DISABLED_cluster) {
> 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
> }
> 
> -/* fuse(4) should honor the filesystem's requested m_readahead parameter */
> -TEST_P(ReadAhead, readahead) {
> -	const char FULLPATH[] = "mountpoint/some_file.txt";
> -	const char RELPATH[] = "some_file.txt";
> -	uint64_t ino = 42;
> -	int fd, i;
> -	ssize_t bufsize = m_maxbcachebuf;
> -	ssize_t filesize = m_maxbcachebuf * 6;
> -	char *rbuf, *contents;
> -
> -	contents = (char*)malloc(filesize);
> -	ASSERT_NE(NULL, contents);
> -	memset(contents, 'X', filesize);
> -	rbuf = (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 = 0; i < (int)get<1>(GetParam()) / m_maxbcachebuf; i++) {
> -		off_t offs = (i + 1) * m_maxbcachebuf;
> -		expect_read(ino, offs, m_maxbcachebuf, m_maxbcachebuf,
> -			contents + offs);
> -	}
> -
> -	fd = 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)));
> 
> Modified: projects/fuse2/tests/sys/fs/fusefs/utils.cc
> ==============================================================================
> --- 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([=](auto in) {
> +				return (in.header.opcode == FUSE_BMAP);
> +			}, Eq(true)),
> +			_)
> +		).Times(AnyNumber())
> +		.WillRepeatedly(Invoke(ReturnErrno(ENOSYS)));
> 	} catch (std::system_error err) {
> 		FAIL() << err.what();
> 	}
> 



More information about the svn-src-projects mailing list