fusefs: respect the server's FUSE_SETXATTR_EXT flag

FUSE protocol 7.33 extended the FUSE_SETXATTR request format.  But the
extension is optional.  The server must opt-in by setting the
FUSE_SETXATTR_IN flag during FUSE_INIT.  We were wrongly using the
extended format for any server using protocol 7.33 or later.

PR:		290547
Co-authored-by:	CismonX <admin@cismon.net>
Fixes:		d5e3cf41e8 ("fusefs: Upgrade FUSE protocol to version 7.33")
MFC after:	3 days
This commit is contained in:
Alan Somers
2025-10-26 12:06:51 -06:00
parent cd7f3e4d9e
commit e8449c0e0f
4 changed files with 59 additions and 18 deletions
+52 -15
View File
@@ -100,7 +100,11 @@ void expect_removexattr(uint64_t ino, const char *attr, int error)
).WillOnce(Invoke(ReturnErrno(error)));
}
void expect_setxattr(uint64_t ino, const char *attr, const char *value,
/*
* Expect a FUSE_SETXATTR request in the format used by protocol 7.33 and
* later, with the FUSE_SETXATTR_EXT bit set.
*/
void expect_setxattr_ext(uint64_t ino, const char *attr, const char *value,
ProcessMockerT r)
{
EXPECT_CALL(*m_mock, process(
@@ -119,16 +123,10 @@ void expect_setxattr(uint64_t ino, const char *attr, const char *value,
).WillOnce(Invoke(r));
}
};
class Xattr_7_32:public FuseTest {
public:
virtual void SetUp()
{
m_kernel_minor_version = 32;
FuseTest::SetUp();
}
/*
* Expect a FUSE_SETXATTR request in the format used by protocol 7.32 and
* earlier.
*/
void expect_setxattr_7_32(uint64_t ino, const char *attr, const char *value,
ProcessMockerT r)
{
@@ -148,6 +146,15 @@ void expect_setxattr_7_32(uint64_t ino, const char *attr, const char *value,
}
};
class Xattr_7_32: public Xattr {
public:
virtual void SetUp()
{
m_kernel_minor_version = 32;
Xattr::SetUp();
}
};
class Getxattr: public Xattr {};
class Listxattr: public Xattr {};
@@ -182,6 +189,13 @@ void TearDown() {
class Removexattr: public Xattr {};
class Setxattr: public Xattr {};
class SetxattrExt: public Setxattr {
public:
virtual void SetUp() {
m_init_flags |= FUSE_SETXATTR_EXT;
Setxattr::SetUp();
}
};
class Setxattr_7_32:public Xattr_7_32 {};
class RofsXattr: public Xattr {
public:
@@ -773,7 +787,7 @@ TEST_F(Setxattr, enosys)
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS));
expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(ENOSYS));
r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value,
value_len);
@@ -800,7 +814,7 @@ TEST_F(Setxattr, enotsup)
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOTSUP));
expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(ENOTSUP));
r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value,
value_len);
@@ -820,7 +834,7 @@ TEST_F(Setxattr, user)
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
expect_setxattr(ino, "user.foo", value, ReturnErrno(0));
expect_setxattr_7_32(ino, "user.foo", value, ReturnErrno(0));
r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value,
value_len);
@@ -839,7 +853,7 @@ TEST_F(Setxattr, system)
ssize_t r;
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
expect_setxattr(ino, "system.foo", value, ReturnErrno(0));
expect_setxattr_7_32(ino, "system.foo", value, ReturnErrno(0));
r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value,
value_len);
@@ -847,6 +861,10 @@ TEST_F(Setxattr, system)
}
/*
* For servers using protocol 7.32 and older, the kernel should use the older
* FUSE_SETXATTR format.
*/
TEST_F(Setxattr_7_32, ok)
{
uint64_t ino = 42;
@@ -863,6 +881,25 @@ TEST_F(Setxattr_7_32, ok)
ASSERT_EQ(value_len, r) << strerror(errno);
}
/*
* Successfully set a user attribute using the extended format
*/
TEST_F(SetxattrExt, user)
{
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, 0, 1);
expect_setxattr_ext(ino, "user.foo", value, ReturnErrno(0));
r = extattr_set_file(FULLPATH, ns, "foo", (const void*)value,
value_len);
ASSERT_EQ(value_len, r) << strerror(errno);
}
TEST_F(RofsXattr, deleteextattr_erofs)
{
uint64_t ino = 42;