svn commit: r346756 - in projects/fuse2: sys/kern tests/sys/fs/fusefs

Alan Somers asomers at FreeBSD.org
Fri Apr 26 17:09:28 UTC 2019


Author: asomers
Date: Fri Apr 26 17:09:26 2019
New Revision: 346756
URL: https://svnweb.freebsd.org/changeset/base/346756

Log:
  fusefs: fix cache invalidation error from r346162
  
  An off-by-one error led to the last page of a write not being removed from
  its object, even though that page's buffer was marked as invalid.
  
  PR:		235774
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/kern/vfs_subr.c
  projects/fuse2/tests/sys/fs/fusefs/write.cc

Modified: projects/fuse2/sys/kern/vfs_subr.c
==============================================================================
--- projects/fuse2/sys/kern/vfs_subr.c	Fri Apr 26 17:01:56 2019	(r346755)
+++ projects/fuse2/sys/kern/vfs_subr.c	Fri Apr 26 17:09:26 2019	(r346756)
@@ -1927,10 +1927,13 @@ v_inval_buf_range(struct vnode *vp, off_t start, off_t
 {
 	struct bufobj *bo;
 	daddr_t startlbn, endlbn;
+	vm_pindex_t startp, endp;
 
 	/* Round "outwards" */
 	startlbn = start / blksize;
 	endlbn = howmany(end, blksize);
+	startp = OFF_TO_IDX(start);
+	endp = OFF_TO_IDX(end + PAGE_SIZE - 1);
 
 	ASSERT_VOP_LOCKED(vp, "v_inval_buf_range");
 
@@ -1960,7 +1963,7 @@ restart:
 		goto restart;
 
 	BO_UNLOCK(bo);
-	vn_pages_remove(vp, OFF_TO_IDX(start), OFF_TO_IDX(end));
+	vn_pages_remove(vp, startp, endp);
 }
 
 /* Like v_inval_buf_range, but operates on whole buffers instead of offsets */

Modified: projects/fuse2/tests/sys/fs/fusefs/write.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/write.cc	Fri Apr 26 17:01:56 2019	(r346755)
+++ projects/fuse2/tests/sys/fs/fusefs/write.cc	Fri Apr 26 17:09:26 2019	(r346756)
@@ -413,17 +413,28 @@ TEST_F(WriteThrough, evicts_read_cache)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
-	const char CONTENTS0[] = "abcdefgh";
-	const char CONTENTS1[] = "ijklmnop";
+	ssize_t bufsize = 65536;
+	/* End the write in the middle of a page */
+	ssize_t wrsize = bufsize - 1000;
+	char *contents0, *contents1, *readbuf, *expected;
 	uint64_t ino = 42;
 	int fd;
-	ssize_t bufsize = strlen(CONTENTS0) + 1;
-	char readbuf[bufsize];
 
+	contents0 = (char*)malloc(bufsize);
+	memset(contents0, 'X', bufsize);
+	contents0[bufsize - 1] = '\0';	// Null-terminate
+	contents1 = (char*)malloc(wrsize);
+	memset(contents1, 'Y', wrsize);
+	readbuf = (char*)calloc(bufsize, 1);
+	expected = (char*)malloc(bufsize);
+	memset(expected, 'Y', wrsize);
+	memset(expected + wrsize, 'X', bufsize - wrsize);
+	expected[bufsize - 1] = '\0';	// Null-terminate
+
 	expect_lookup(RELPATH, ino, bufsize);
 	expect_open(ino, 0, 1);
-	expect_read(ino, 0, bufsize, bufsize, CONTENTS0);
-	expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS1);
+	expect_read(ino, 0, bufsize, bufsize, contents0);
+	expect_write(ino, 0, wrsize, wrsize, 0, contents1);
 
 	fd = open(FULLPATH, O_RDWR);
 	EXPECT_LE(0, fd) << strerror(errno);
@@ -433,13 +444,13 @@ TEST_F(WriteThrough, evicts_read_cache)
 
 	// Write directly, evicting cache
 	ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
-	ASSERT_EQ(bufsize, write(fd, CONTENTS1, bufsize)) << strerror(errno);
+	ASSERT_EQ(wrsize, write(fd, contents1, wrsize)) << strerror(errno);
 
 	// Read again.  Cache should be bypassed
-	expect_read(ino, 0, bufsize, bufsize, CONTENTS1);
+	expect_read(ino, 0, bufsize, bufsize, expected);
 	ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
 	ASSERT_EQ(bufsize, read(fd, readbuf, bufsize)) << strerror(errno);
-	ASSERT_STREQ(readbuf, CONTENTS1);
+	ASSERT_STREQ(readbuf, expected);
 
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
 }


More information about the svn-src-projects mailing list