fusefs: fix a panic in a stale vnode situation

Don't panic if the server changes the file type of a file without us first
deleting it.  That could indicate a buggy server, but it could also be the
result of one of several race conditions.  Return EAGAIN as we do elsewhere.

Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-04-11 22:32:34 +00:00
parent 4683b90591
commit 64f31d4f3b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=346137
2 changed files with 31 additions and 1 deletions

View File

@ -233,7 +233,17 @@ fuse_vnode_alloc(struct mount *mp,
return (err);
if (*vpp) {
MPASS((*vpp)->v_type == vtyp && (*vpp)->v_data != NULL);
if ((*vpp)->v_type != vtyp) {
/*
* STALE vnode! This probably indicates a buggy
* server, but it could also be the result of a race
* between FUSE_LOOKUP and another client's
* FUSE_UNLINK/FUSE_CREATE
*/
fuse_internal_vnode_disappear(*vpp);
return (EAGAIN);
}
MPASS((*vpp)->v_data != NULL);
SDT_PROBE2(fuse, , node, trace, 1, "vnode taken from hash");
return (0);
}

View File

@ -349,3 +349,23 @@ TEST_F(Lookup, subdir)
*/
ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno);
}
/*
* The server returns two different vtypes for the same nodeid. This is a bad
* server! But we shouldn't crash.
*/
TEST_F(Lookup, vtype_conflict)
{
const char FIRSTFULLPATH[] = "mountpoint/foo";
const char SECONDFULLPATH[] = "mountpoint/bar";
const char FIRSTRELPATH[] = "foo";
const char SECONDRELPATH[] = "bar";
uint64_t ino = 42;
expect_lookup(FIRSTRELPATH, ino, S_IFREG | 0644, 0, 1, UINT64_MAX);
expect_lookup(SECONDRELPATH, ino, S_IFDIR | 0755, 0, 1, UINT64_MAX);
ASSERT_EQ(0, access(FIRSTFULLPATH, F_OK)) << strerror(errno);
ASSERT_EQ(-1, access(SECONDFULLPATH, F_OK));
ASSERT_EQ(EAGAIN, errno);
}