fusefs: Handle ENOSYS for all remaining opcodes
For many FUSE opcodes, an error of ENOSYS has special meaning. fusefs already handled some of those; this commit adds handling for the remainder: * FUSE_FSYNC, FUSE_FSYNCDIR: ENOSYS means "success, and automatically return success without calling the daemon from now on" * All extattr operations: ENOSYS means "fail EOPNOTSUPP, and automatically do it without calling the daemon from now on" PR: 236557 Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
b349700a04
commit
1f4a83f981
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=346141
@ -259,6 +259,7 @@ fuse_internal_fsync(struct vnode *vp,
|
|||||||
struct fuse_dispatcher fdi;
|
struct fuse_dispatcher fdi;
|
||||||
struct fuse_filehandle *fufh;
|
struct fuse_filehandle *fufh;
|
||||||
struct fuse_vnode_data *fvdat = VTOFUD(vp);
|
struct fuse_vnode_data *fvdat = VTOFUD(vp);
|
||||||
|
struct mount *mp = vnode_mount(vp);
|
||||||
int op = FUSE_FSYNC;
|
int op = FUSE_FSYNC;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -269,6 +270,9 @@ fuse_internal_fsync(struct vnode *vp,
|
|||||||
if (vnode_isdir(vp))
|
if (vnode_isdir(vp))
|
||||||
op = FUSE_FSYNCDIR;
|
op = FUSE_FSYNCDIR;
|
||||||
|
|
||||||
|
if (!fsess_isimpl(mp, op))
|
||||||
|
return 0;
|
||||||
|
|
||||||
fdisp_init(&fdi, sizeof(*ffsi));
|
fdisp_init(&fdi, sizeof(*ffsi));
|
||||||
/*
|
/*
|
||||||
* fsync every open file handle for this file, because we can't be sure
|
* fsync every open file handle for this file, because we can't be sure
|
||||||
@ -293,6 +297,12 @@ fuse_internal_fsync(struct vnode *vp,
|
|||||||
fuse_internal_fsync_callback);
|
fuse_internal_fsync_callback);
|
||||||
fuse_insert_message(fdi.tick);
|
fuse_insert_message(fdi.tick);
|
||||||
}
|
}
|
||||||
|
if (err == ENOSYS) {
|
||||||
|
/* ENOSYS means "success, and don't call again" */
|
||||||
|
fsess_set_notimpl(mp, op);
|
||||||
|
err = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
fdisp_destroy(&fdi);
|
fdisp_destroy(&fdi);
|
||||||
|
|
||||||
|
@ -1893,6 +1893,9 @@ fuse_vnop_getextattr(struct vop_getextattr_args *ap)
|
|||||||
if (fuse_isdeadfs(vp))
|
if (fuse_isdeadfs(vp))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!fsess_isimpl(mp, FUSE_GETXATTR))
|
||||||
|
return EOPNOTSUPP;
|
||||||
|
|
||||||
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
|
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -1927,8 +1930,10 @@ fuse_vnop_getextattr(struct vop_getextattr_args *ap)
|
|||||||
|
|
||||||
err = fdisp_wait_answ(&fdi);
|
err = fdisp_wait_answ(&fdi);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
if (err == ENOSYS)
|
if (err == ENOSYS) {
|
||||||
fsess_set_notimpl(mp, FUSE_GETXATTR);
|
fsess_set_notimpl(mp, FUSE_GETXATTR);
|
||||||
|
err = EOPNOTSUPP;
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1974,12 +1979,23 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap)
|
|||||||
if (fuse_isdeadfs(vp))
|
if (fuse_isdeadfs(vp))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!fsess_isimpl(mp, FUSE_SETXATTR))
|
||||||
|
return EOPNOTSUPP;
|
||||||
|
|
||||||
if (vfs_isrdonly(mp))
|
if (vfs_isrdonly(mp))
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
/* Deleting xattrs must use VOP_DELETEEXTATTR instead */
|
/* Deleting xattrs must use VOP_DELETEEXTATTR instead */
|
||||||
if (ap->a_uio == NULL)
|
if (ap->a_uio == NULL) {
|
||||||
return (EINVAL);
|
/*
|
||||||
|
* If we got here as fallback from VOP_DELETEEXTATTR, then
|
||||||
|
* return EOPNOTSUPP.
|
||||||
|
*/
|
||||||
|
if (!fsess_isimpl(mp, FUSE_REMOVEXATTR))
|
||||||
|
return (EOPNOTSUPP);
|
||||||
|
else
|
||||||
|
return (EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td,
|
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td,
|
||||||
VWRITE);
|
VWRITE);
|
||||||
@ -2013,10 +2029,9 @@ fuse_vnop_setextattr(struct vop_setextattr_args *ap)
|
|||||||
|
|
||||||
err = fdisp_wait_answ(&fdi);
|
err = fdisp_wait_answ(&fdi);
|
||||||
|
|
||||||
if (err != 0) {
|
if (err == ENOSYS) {
|
||||||
if (err == ENOSYS)
|
fsess_set_notimpl(mp, FUSE_SETXATTR);
|
||||||
fsess_set_notimpl(mp, FUSE_SETXATTR);
|
err = EOPNOTSUPP;
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -2113,6 +2128,9 @@ fuse_vnop_listextattr(struct vop_listextattr_args *ap)
|
|||||||
if (fuse_isdeadfs(vp))
|
if (fuse_isdeadfs(vp))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!fsess_isimpl(mp, FUSE_LISTXATTR))
|
||||||
|
return EOPNOTSUPP;
|
||||||
|
|
||||||
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
|
err = fuse_extattr_check_cred(vp, ap->a_attrnamespace, cred, td, VREAD);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
@ -2141,8 +2159,10 @@ fuse_vnop_listextattr(struct vop_listextattr_args *ap)
|
|||||||
|
|
||||||
err = fdisp_wait_answ(&fdi);
|
err = fdisp_wait_answ(&fdi);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
if (err == ENOSYS)
|
if (err == ENOSYS) {
|
||||||
fsess_set_notimpl(mp, FUSE_LISTXATTR);
|
fsess_set_notimpl(mp, FUSE_LISTXATTR);
|
||||||
|
err = EOPNOTSUPP;
|
||||||
|
}
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2221,6 +2241,9 @@ fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap)
|
|||||||
if (fuse_isdeadfs(vp))
|
if (fuse_isdeadfs(vp))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
|
||||||
|
if (!fsess_isimpl(mp, FUSE_REMOVEXATTR))
|
||||||
|
return EOPNOTSUPP;
|
||||||
|
|
||||||
if (vfs_isrdonly(mp))
|
if (vfs_isrdonly(mp))
|
||||||
return EROFS;
|
return EROFS;
|
||||||
|
|
||||||
@ -2246,9 +2269,9 @@ fuse_vnop_deleteextattr(struct vop_deleteextattr_args *ap)
|
|||||||
ap->a_name);
|
ap->a_name);
|
||||||
|
|
||||||
err = fdisp_wait_answ(&fdi);
|
err = fdisp_wait_answ(&fdi);
|
||||||
if (err != 0) {
|
if (err == ENOSYS) {
|
||||||
if (err == ENOSYS)
|
fsess_set_notimpl(mp, FUSE_REMOVEXATTR);
|
||||||
fsess_set_notimpl(mp, FUSE_REMOVEXATTR);
|
err = EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
fdisp_destroy(&fdi);
|
fdisp_destroy(&fdi);
|
||||||
|
@ -179,8 +179,7 @@ TEST_F(Fsync, eio)
|
|||||||
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
|
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
|
||||||
* to the filesystem daemon
|
* to the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(Fsync, enosys)
|
||||||
TEST_F(Fsync, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||||
const char RELPATH[] = "some_file.txt";
|
const char RELPATH[] = "some_file.txt";
|
||||||
|
@ -124,8 +124,7 @@ TEST_F(FsyncDir, eio)
|
|||||||
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
|
* subsequent calls to VOP_FSYNC will succeed automatically without being sent
|
||||||
* to the filesystem daemon
|
* to the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(FsyncDir, enosys)
|
||||||
TEST_F(FsyncDir, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
const char FULLPATH[] = "mountpoint/some_dir";
|
const char FULLPATH[] = "mountpoint/some_dir";
|
||||||
const char RELPATH[] = "some_dir";
|
const char RELPATH[] = "some_dir";
|
||||||
@ -134,7 +133,7 @@ TEST_F(FsyncDir, DISABLED_enosys)
|
|||||||
|
|
||||||
expect_lookup(RELPATH, ino);
|
expect_lookup(RELPATH, ino);
|
||||||
expect_opendir(ino);
|
expect_opendir(ino);
|
||||||
expect_fsyncdir(ino, FUSE_FSYNC_FDATASYNC, ENOSYS);
|
expect_fsyncdir(ino, 0, ENOSYS);
|
||||||
|
|
||||||
fd = open(FULLPATH, O_DIRECTORY);
|
fd = open(FULLPATH, O_DIRECTORY);
|
||||||
ASSERT_LE(0, fd) << strerror(errno);
|
ASSERT_LE(0, fd) << strerror(errno);
|
||||||
|
@ -141,15 +141,14 @@ TEST_F(Getxattr, enoattr)
|
|||||||
* failure and all future VOP_GETEXTATTR calls will fail with EOPNOTSUPP
|
* failure and all future VOP_GETEXTATTR calls will fail with EOPNOTSUPP
|
||||||
* without querying the filesystem daemon
|
* without querying the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(Getxattr, enosys)
|
||||||
TEST_F(Getxattr, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
char data[80];
|
char data[80];
|
||||||
uint64_t ino = 42;
|
uint64_t ino = 42;
|
||||||
int ns = EXTATTR_NAMESPACE_USER;
|
int ns = EXTATTR_NAMESPACE_USER;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
|
||||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
|
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
|
||||||
expect_getxattr(ino, "user.foo", ReturnErrno(ENOSYS));
|
expect_getxattr(ino, "user.foo", ReturnErrno(ENOSYS));
|
||||||
|
|
||||||
r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data));
|
r = extattr_get_file(FULLPATH, ns, "foo", data, sizeof(data));
|
||||||
@ -265,13 +264,12 @@ TEST_F(Getxattr, user)
|
|||||||
* failure and all future VOP_LISTEXTATTR calls will fail with EOPNOTSUPP
|
* failure and all future VOP_LISTEXTATTR calls will fail with EOPNOTSUPP
|
||||||
* without querying the filesystem daemon
|
* without querying the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(Listxattr, enosys)
|
||||||
TEST_F(Listxattr, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
uint64_t ino = 42;
|
uint64_t ino = 42;
|
||||||
int ns = EXTATTR_NAMESPACE_USER;
|
int ns = EXTATTR_NAMESPACE_USER;
|
||||||
|
|
||||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
|
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
|
||||||
expect_listxattr(ino, 0, ReturnErrno(ENOSYS));
|
expect_listxattr(ino, 0, ReturnErrno(ENOSYS));
|
||||||
|
|
||||||
ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0));
|
ASSERT_EQ(-1, extattr_list_file(FULLPATH, ns, NULL, 0));
|
||||||
@ -485,13 +483,12 @@ TEST_F(Removexattr, enoattr)
|
|||||||
* failure and all future VOP_DELETEEXTATTR calls will fail with EOPNOTSUPP
|
* failure and all future VOP_DELETEEXTATTR calls will fail with EOPNOTSUPP
|
||||||
* without querying the filesystem daemon
|
* without querying the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(Removexattr, enosys)
|
||||||
TEST_F(Removexattr, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
uint64_t ino = 42;
|
uint64_t ino = 42;
|
||||||
int ns = EXTATTR_NAMESPACE_USER;
|
int ns = EXTATTR_NAMESPACE_USER;
|
||||||
|
|
||||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
|
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
|
||||||
expect_removexattr(ino, "user.foo", ENOSYS);
|
expect_removexattr(ino, "user.foo", ENOSYS);
|
||||||
|
|
||||||
ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo"));
|
ASSERT_EQ(-1, extattr_delete_file(FULLPATH, ns, "foo"));
|
||||||
@ -533,8 +530,7 @@ TEST_F(Removexattr, system)
|
|||||||
* failure and all future VOP_SETEXTATTR calls will fail with EOPNOTSUPP
|
* failure and all future VOP_SETEXTATTR calls will fail with EOPNOTSUPP
|
||||||
* without querying the filesystem daemon
|
* without querying the filesystem daemon
|
||||||
*/
|
*/
|
||||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236557 */
|
TEST_F(Setxattr, enosys)
|
||||||
TEST_F(Setxattr, DISABLED_enosys)
|
|
||||||
{
|
{
|
||||||
uint64_t ino = 42;
|
uint64_t ino = 42;
|
||||||
const char value[] = "whatever";
|
const char value[] = "whatever";
|
||||||
@ -542,7 +538,7 @@ TEST_F(Setxattr, DISABLED_enosys)
|
|||||||
int ns = EXTATTR_NAMESPACE_USER;
|
int ns = EXTATTR_NAMESPACE_USER;
|
||||||
ssize_t r;
|
ssize_t r;
|
||||||
|
|
||||||
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
|
expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 2);
|
||||||
expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS));
|
expect_setxattr(ino, "user.foo", value, ReturnErrno(ENOSYS));
|
||||||
|
|
||||||
r = extattr_set_file(FULLPATH, ns, "foo", (void*)value, value_len);
|
r = extattr_set_file(FULLPATH, ns, "foo", (void*)value, value_len);
|
||||||
|
Loading…
Reference in New Issue
Block a user