fusefs: correctly handle cacheable negative LOOKUP responses

The FUSE protocol allows for LOOKUP to return a cacheable negative response,
which means that the file doesn't exist and the kernel can cache its
nonexistence.  As of this commit fusefs doesn't cache the nonexistence, but
it does correctly handle such responses.  Prior to this commit attempting to
create a file, even with O_CREAT would fail with ENOENT if the daemon
returned a cacheable negative response.

PR:		236231
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-03-21 23:31:10 +00:00
parent 915012e0d0
commit 6248288e97
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=345399
4 changed files with 9 additions and 19 deletions

View File

@ -747,6 +747,7 @@ fuse_vnop_lookup(struct vop_lookup_args *ap)
* but it's also cacheable (which we keep
* keep on doing not as of writing this)
*/
fdi.answ_stat = ENOENT;
lookup_err = ENOENT;
} else if (nid == FUSE_ROOT_ID) {
lookup_err = EINVAL;

View File

@ -185,8 +185,7 @@ TEST_F(Create, DISABLED_Enosys)
/*
* Creating a new file after FUSE_LOOKUP returned a negative cache entry
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Create, DISABLED_entry_cache_negative)
TEST_F(Create, entry_cache_negative)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
@ -240,8 +239,7 @@ TEST_F(Create, DISABLED_entry_cache_negative)
/*
* Creating a new file should purge any negative namecache entries
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Create, DISABLED_entry_cache_negative_purge)
TEST_F(Create, entry_cache_negative_purge)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";

View File

@ -69,8 +69,7 @@ TEST_F(Mkdir, emlink)
/*
* Creating a new directory after FUSE_LOOKUP returned a negative cache entry
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Mkdir, DISABLED_entry_cache_negative)
TEST_F(Mkdir, entry_cache_negative)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
@ -109,8 +108,7 @@ TEST_F(Mkdir, DISABLED_entry_cache_negative)
/*
* Creating a new directory should purge any negative namecache entries
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Mkdir, DISABLED_entry_cache_negative_purge)
TEST_F(Mkdir, entry_cache_negative_purge)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";

View File

@ -86,8 +86,7 @@ TEST_F(Rename, enoent)
/*
* Renaming a file after FUSE_LOOKUP returned a negative cache entry for dst
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Rename, DISABLED_entry_cache_negative)
TEST_F(Rename, entry_cache_negative)
{
const char FULLDST[] = "mountpoint/dst";
const char RELDST[] = "dst";
@ -126,8 +125,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative)
/*
* Renaming a file should purge any negative namecache entries for the dst
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */
TEST_F(Rename, DISABLED_entry_cache_negative_purge)
TEST_F(Rename, entry_cache_negative_purge)
{
const char FULLDST[] = "mountpoint/dst";
const char RELDST[] = "dst";
@ -136,12 +134,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative_purge)
// FUSE hardcodes the mountpoint to inode 1
uint64_t dst_dir_ino = 1;
uint64_t ino = 42;
/*
* Set entry_valid = 0 because this test isn't concerned with whether
* or not we actually cache negative entries, only with whether we
* interpret negative cache responses correctly.
*/
struct timespec entry_valid = {.tv_sec = 0, .tv_nsec = 0};
struct timespec entry_valid = {.tv_sec = TIME_T_MAX, .tv_nsec = 0};
expect_lookup(RELSRC, ino, S_IFREG | 0644, 0, 1);
/* LOOKUP returns a negative cache entry for dst */
@ -164,7 +157,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative_purge)
ASSERT_EQ(0, rename(FULLSRC, FULLDST)) << strerror(errno);
/* Finally, a subsequent lookup should query the daemon */
expect_lookup(RELSRC, ino, S_IFREG | 0644, 0, 1);
expect_lookup(RELDST, ino, S_IFREG | 0644, 0, 1);
ASSERT_EQ(0, access(FULLDST, F_OK)) << strerror(errno);
}