fuse(4): add tests for ENOSYS special cases

PR:		236557
Sponsored by:	The FreeBSD Foundation
This commit is contained in:
Alan Somers 2019-03-15 18:06:51 +00:00
parent 9038479127
commit 71885041ce
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=345195
6 changed files with 223 additions and 18 deletions

View File

@ -41,6 +41,18 @@ using namespace testing;
class Access: public FuseTest {
public:
void expect_access(uint64_t ino, mode_t access_mode, int error)
{
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
return (in->header.opcode == FUSE_ACCESS &&
in->header.nodeid == ino &&
in->body.access.mask == access_mode);
}, Eq(true)),
_)
).WillOnce(Invoke(ReturnErrno(error)));
}
void expect_lookup(const char *relpath, uint64_t ino)
{
FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1);
@ -59,20 +71,33 @@ TEST_F(Access, DISABLED_eaccess)
mode_t access_mode = X_OK;
expect_lookup(RELPATH, ino);
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
return (in->header.opcode == FUSE_ACCESS &&
in->header.nodeid == ino &&
in->body.access.mask == access_mode);
}, Eq(true)),
_)
).WillOnce(Invoke(ReturnErrno(EACCES)));
expect_access(ino, access_mode, EACCES);
ASSERT_NE(0, access(FULLPATH, access_mode));
ASSERT_EQ(EACCES, errno);
}
/*
* If the filesystem returns ENOSYS, then it is treated as a permanent success,
* and subsequent VOP_ACCESS calls will succeed automatically without querying
* the daemon.
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */
TEST_F(Access, DISABLED_enosys)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
uint64_t ino = 42;
mode_t access_mode = R_OK;
expect_lookup(RELPATH, ino);
expect_access(ino, access_mode, ENOSYS);
ASSERT_EQ(0, access(FULLPATH, access_mode)) << strerror(errno);
ASSERT_EQ(0, access(FULLPATH, access_mode)) << strerror(errno);
}
/* The successful case of FUSE_ACCESS. */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */
TEST_F(Access, DISABLED_ok)
@ -83,14 +108,7 @@ TEST_F(Access, DISABLED_ok)
mode_t access_mode = R_OK;
expect_lookup(RELPATH, ino);
EXPECT_CALL(*m_mock, process(
ResultOf([=](auto in) {
return (in->header.opcode == FUSE_ACCESS &&
in->header.nodeid == ino &&
in->body.access.mask == access_mode);
}, Eq(true)),
_)
).WillOnce(Invoke(ReturnErrno(0)));
expect_access(ino, access_mode, 0);
ASSERT_EQ(0, access(FULLPATH, access_mode)) << strerror(errno);
}

View File

@ -114,6 +114,7 @@ TEST_F(Create, eexist)
* to FUSE_MKNOD/FUSE_OPEN
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236236 */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Create, DISABLED_Enosys)
{
const char FULLPATH[] = "mountpoint/some_file.txt";

View File

@ -134,6 +134,35 @@ TEST_F(Flush, DISABLED_eio)
ASSERT_TRUE(0 == close(fd) || errno == EIO) << strerror(errno);
}
/*
* If the filesystem returns ENOSYS, it will be treated as success and
* no more FUSE_FLUSH operations will be sent to the daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236405 */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Flush, DISABLED_enosys)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
uint64_t ino = 42;
int fd, fd2;
expect_lookup(RELPATH, ino);
expect_open(ino, 0, 1);
expect_getattr(ino, 0);
/* On the 2nd close, FUSE_FLUSH won't be sent at all */
expect_flush(ino, 1, 0, ReturnErrno(ENOSYS));
expect_release();
fd = open(FULLPATH, O_WRONLY);
EXPECT_LE(0, fd) << strerror(errno);
fd2 = dup(fd);
EXPECT_EQ(0, close(fd2)) << strerror(errno);
EXPECT_EQ(0, close(fd)) << strerror(errno);
}
/* A FUSE_FLUSH should be sent on close(2) */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236405 */
TEST_F(Flush, DISABLED_flush)

View File

@ -56,7 +56,6 @@ void expect_fsync(uint64_t ino, uint32_t flags, int error)
ResultOf([=](auto in) {
return (in->header.opcode == FUSE_FSYNC &&
in->header.nodeid == ino &&
//(pid_t)in->header.pid == getpid() &&
in->body.fsync.fh == FH &&
in->body.fsync.fsync_flags == flags);
}, Eq(true)),
@ -175,6 +174,39 @@ TEST_F(Fsync, DISABLED_eio)
/* Deliberately leak fd. close(2) will be tested in release.cc */
}
/*
* If the filesystem returns ENOSYS, it will be treated as success and
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
* to the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236474 */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Fsync, DISABLED_enosys)
{
const char FULLPATH[] = "mountpoint/some_file.txt";
const char RELPATH[] = "some_file.txt";
const char *CONTENTS = "abcdefgh";
ssize_t bufsize = strlen(CONTENTS);
uint64_t ino = 42;
int fd;
expect_lookup(RELPATH, ino);
expect_open(ino, 0, 1);
expect_getattr(ino, 0);
expect_write(ino, bufsize, CONTENTS);
expect_fsync(ino, FUSE_FSYNC_FDATASYNC, ENOSYS);
fd = open(FULLPATH, O_RDWR);
ASSERT_LE(0, fd) << strerror(errno);
ASSERT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno);
EXPECT_EQ(0, fdatasync(fd));
/* Subsequent calls shouldn't query the daemon*/
EXPECT_EQ(0, fdatasync(fd));
/* Deliberately leak fd. close(2) will be tested in release.cc */
}
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236474 */
TEST_F(Fsync, DISABLED_fdatasync)
{

View File

@ -119,6 +119,34 @@ TEST_F(FsyncDir, DISABLED_eio)
/* Deliberately leak fd. close(2) will be tested in release.cc */
}
/*
* If the filesystem returns ENOSYS, it will be treated as success and
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
* to the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236474 */
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(FsyncDir, DISABLED_enosys)
{
const char FULLPATH[] = "mountpoint/some_dir";
const char RELPATH[] = "some_dir";
uint64_t ino = 42;
int fd;
expect_lookup(RELPATH, ino);
expect_opendir(ino);
expect_fsyncdir(ino, FUSE_FSYNC_FDATASYNC, ENOSYS);
fd = open(FULLPATH, O_DIRECTORY);
ASSERT_LE(0, fd) << strerror(errno);
EXPECT_EQ(0, fsync(fd)) << strerror(errno);
/* Subsequent calls shouldn't query the daemon*/
EXPECT_EQ(0, fsync(fd)) << strerror(errno);
/* Deliberately leak fd. close(2) will be tested in release.cc */
}
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236474 */
TEST_F(FsyncDir, DISABLED_fsyncdata)
{

View File

@ -129,6 +129,32 @@ TEST_F(Getxattr, enoattr)
ASSERT_EQ(ENOATTR, errno);
}
/*
* If the filesystem returns ENOSYS, then it will be treated as a permanent
* failure and all future VOP_GETEXTATTR calls will fail with EOPNOTSUPP
* without querying the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Getxattr, DISABLED_enosys)
{
char data[80];
uint64_t ino = 42;
int ns = EXTATTR_NAMESPACE_USER;
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 1);
expect_getxattr(ino, "user.foo", ReturnErrno(ENOSYS));
r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data));
ASSERT_EQ(-1, r);
EXPECT_EQ(EOPNOTSUPP, errno);
/* Subsequent attempts should not query the filesystem at all */
r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data));
ASSERT_EQ(-1, r);
EXPECT_EQ(EOPNOTSUPP, errno);
}
/*
* On FreeBSD, if the user passes an insufficiently large buffer then the
* filesystem is supposed to copy as much of the attribute's value as will fit.
@ -227,6 +253,28 @@ TEST_F(Getxattr, user)
EXPECT_STREQ(value, data);
}
/*
* If the filesystem returns ENOSYS, then it will be treated as a permanent
* failure and all future VOP_LISTEXTATTR calls will fail with EOPNOTSUPP
* without querying the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Listxattr, DISABLED_enosys)
{
uint64_t ino = 42;
int ns = EXTATTR_NAMESPACE_USER;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 1);
expect_listxattr(ino, 0, ReturnErrno(ENOSYS));
ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0));
EXPECT_EQ(EOPNOTSUPP, errno);
/* Subsequent attempts should not query the filesystem at all */
ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0));
EXPECT_EQ(EOPNOTSUPP, errno);
}
/*
* Listing extended attributes failed because they aren't configured on this
* filesystem
@ -425,6 +473,28 @@ TEST_F(Removexattr, enoattr)
ASSERT_EQ(ENOATTR, errno);
}
/*
* If the filesystem returns ENOSYS, then it will be treated as a permanent
* failure and all future VOP_DELETEEXTATTR calls will fail with EOPNOTSUPP
* without querying the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Removexattr, DISABLED_enosys)
{
uint64_t ino = 42;
int ns = EXTATTR_NAMESPACE_USER;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 1);
expect_removexattr(ino, "user.foo", ENOSYS);
ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo"));
EXPECT_EQ(EOPNOTSUPP, errno);
/* Subsequent attempts should not query the filesystem at all */
ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo"));
EXPECT_EQ(EOPNOTSUPP, errno);
}
/* Successfully remove a user xattr */
TEST_F(Removexattr, user)
{
@ -451,6 +521,33 @@ TEST_F(Removexattr, system)
<< strerror(errno);
}
/*
* If the filesystem returns ENOSYS, then it will be treated as a permanent
* failure and all future VOP_SETEXTATTR calls will fail with EOPNOTSUPP
* without querying the filesystem daemon
*/
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
TEST_F(Setxattr, DISABLED_enosys)
{
uint64_t ino = 42;
const char value[] = "whatever";
ssize_t value_len = strlen(value) + 1;
int ns = EXTATTR_NAMESPACE_USER;
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 1);
expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS));
r = extattr_set_file(FULLPATH, ns, "foo", (void*)value, value_len);
ASSERT_EQ(-1, r);
EXPECT_EQ(EOPNOTSUPP, errno);
/* Subsequent attempts should not query the filesystem at all */
r = extattr_set_file(FULLPATH, ns, "foo", (void*)value, value_len);
ASSERT_EQ(-1, r);
EXPECT_EQ(EOPNOTSUPP, errno);
}
/*
* SETXATTR will return ENOTSUP if the namespace is invalid or the filesystem
* as currently configured doesn't support extended attributes.