svn commit: r349038 - in projects/fuse2: sys/fs/fuse tests/sys/fs/fusefs
Alan Somers
asomers at FreeBSD.org
Fri Jun 14 19:47:50 UTC 2019
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 */
}
More information about the svn-src-projects
mailing list