Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Jun 2019 19:47:49 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r349038 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Message-ID:  <201906141947.x5EJlnqu060274@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri Jun 14 19:47:48 2019
New Revision: 349038
URL: https://svnweb.freebsd.org/changeset/base/349038

Log:
  fusefs: fix the "write-through" of write-through cacheing
  
  Our fusefs(5) module supports three cache modes: uncached, write-through,
  and write-back.  However, the write-through mode (which is the default) has
  never actually worked as its name suggests.  Rather, it's always been more
  like "write-around".  It wrote directly, bypassing the cache.  The cache
  would only be populated by a subsequent read of the same data.
  
  This commit fixes that problem.  Now the write-through mode works as one
  would expect: write(2) immediately adds data to the cache and then blocks
  while the daemon processes the write operation.
  
  A side effect of this change is that non-cache-block-aligned writes will now
  incur a read-modify-write cycle of the cache block.  The old behavior
  (bypassing write cache entirely) can still be achieved by opening a file
  with O_DIRECT.
  
  PR:		237588
  Sponsored by:	The FreeBSD Foundation

Modified:
  projects/fuse2/sys/fs/fuse/fuse_io.c
  projects/fuse2/tests/sys/fs/fusefs/write.cc

Modified: projects/fuse2/sys/fs/fuse/fuse_io.c
==============================================================================
--- projects/fuse2/sys/fs/fuse/fuse_io.c	Fri Jun 14 18:33:41 2019	(r349037)
+++ projects/fuse2/sys/fs/fuse/fuse_io.c	Fri Jun 14 19:47:48 2019	(r349038)
@@ -219,13 +219,7 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, in
 		}
 		break;
 	case UIO_WRITE:
-		/*
-		 * Kludge: simulate write-through caching via write-around
-		 * caching.  Same effect, as far as never caching dirty data,
-		 * but slightly pessimal in that newly written data is not
-		 * cached.
-		 */
-		if (directio || fuse_data_cache_mode == FUSE_CACHE_WT) {
+		if (directio) {
 			const int iosize = fuse_iosize(vp);
 			off_t start, end, filesize;
 
@@ -250,6 +244,8 @@ fuse_io_dispatch(struct vnode *vp, struct uio *uio, in
 		} else {
 			SDT_PROBE2(fusefs, , io, trace, 1,
 				"buffered write of vnode");
+			if (fuse_data_cache_mode == FUSE_CACHE_WT)
+				ioflag |= IO_SYNC;
 			err = fuse_write_biobackend(vp, uio, cred, fufh, ioflag,
 				pid);
 		}

Modified: projects/fuse2/tests/sys/fs/fusefs/write.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fusefs/write.cc	Fri Jun 14 18:33:41 2019	(r349037)
+++ projects/fuse2/tests/sys/fs/fusefs/write.cc	Fri Jun 14 19:47:48 2019	(r349038)
@@ -531,60 +531,13 @@ TEST_F(Write, mmap)
 	free(zeros);
 }
 
-/* In WriteThrough mode, a write should evict overlapping cached data */
-TEST_F(WriteThrough, evicts_read_cache)
-{
-	const char FULLPATH[] = "mountpoint/some_file.txt";
-	const char RELPATH[] = "some_file.txt";
-	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;
-
-	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, wrsize, wrsize, contents1);
-
-	fd = open(FULLPATH, O_RDWR);
-	EXPECT_LE(0, fd) << strerror(errno);
-
-	// Prime cache
-	ASSERT_EQ(bufsize, read(fd, readbuf, bufsize)) << strerror(errno);
-
-	// Write directly, evicting cache
-	ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
-	ASSERT_EQ(wrsize, write(fd, contents1, wrsize)) << strerror(errno);
-
-	// Read again.  Cache should be bypassed
-	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, expected);
-
-	/* Deliberately leak fd.  close(2) will be tested in release.cc */
-}
-
 TEST_F(WriteThrough, pwrite)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
 	const char *CONTENTS = "abcdefgh";
 	uint64_t ino = 42;
-	uint64_t offset = 4096;
+	uint64_t offset = 65536;
 	int fd;
 	ssize_t bufsize = strlen(CONTENTS);
 
@@ -901,11 +854,7 @@ TEST_F(WriteBack, o_direct)
 /*
  * Without direct_io, writes should be committed to cache
  */
-/* 
- * Disabled because we don't yet implement write-through caching.  No bugzilla
- * entry, because that's a feature request, not a bug.
- */
-TEST_F(WriteThrough, DISABLED_writethrough)
+TEST_F(WriteThrough, writethrough)
 {
 	const char FULLPATH[] = "mountpoint/some_file.txt";
 	const char RELPATH[] = "some_file.txt";
@@ -927,6 +876,7 @@ TEST_F(WriteThrough, DISABLED_writethrough)
 	 * A subsequent read should be serviced by cache, without querying the
 	 * filesystem daemon
 	 */
+	ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
 	ASSERT_EQ(bufsize, read(fd, readbuf, bufsize)) << strerror(errno);
 	/* Deliberately leak fd.  close(2) will be tested in release.cc */
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906141947.x5EJlnqu060274>