On Mon, 4 Jul 2022 at 20:36, Christian Kohlschütter <christian@xxxxxxxxxxxxxxxx> wrote: > > overlayfs may fail to complete updates when a filesystem lacks > fileattr/xattr syscall support and responds with an ENOSYS error code, > resulting in an unexpected "Function not implemented" error. Issue seems to be with fuse: nothing should be returning ENOSYS to userspace except the syscall lookup code itself. ENOSYS means that the syscall does not exist. Fuse uses ENOSYS in the protocol to indicate that the filesystem does not support that operation, but that's not the value that the filesystem should be returning to userspace. The getxattr/setxattr implementations already translate ENOSYS to EOPNOTSUPP, but ioctl doesn't. The attached patch (untested) should do this. Can you please give it a try? Thanks, Miklos
--- fs/fuse/ioctl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -9,6 +9,17 @@ #include <linux/compat.h> #include <linux/fileattr.h> +static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args) +{ + ssize_t ret = fuse_simple_request(fm, args); + + /* Translate ENOSYS, which shouldn't be returned from fs */ + if (ret == -ENOSYS) + ret = -ENOTTY; + + return ret; +} + /* * CUSE servers compiled on 32bit broke on 64bit kernels because the * ABI was defined to be 'struct iovec' which is different on 32bit @@ -259,7 +270,7 @@ long fuse_do_ioctl(struct file *file, un ap.args.out_pages = true; ap.args.out_argvar = true; - transferred = fuse_simple_request(fm, &ap.args); + transferred = fuse_send_ioctl(fm, &ap.args); err = transferred; if (transferred < 0) goto out; @@ -393,7 +404,7 @@ static int fuse_priv_ioctl(struct inode args.out_args[1].size = inarg.out_size; args.out_args[1].value = ptr; - err = fuse_simple_request(fm, &args); + err = fuse_send_ioctl(fm, &args); if (!err) { if (outarg.result < 0) err = outarg.result;