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