cache ENOSYS on some optional functions
diff --git a/kernel/dir.c b/kernel/dir.c
index 110a472..e941e3e 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -783,6 +783,9 @@
if (size > FUSE_XATTR_SIZE_MAX)
return -E2BIG;
+ if (fc->no_setxattr)
+ return -EOPNOTSUPP;
+
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
inarg.flags = flags;
@@ -797,6 +800,10 @@
in.args[2].size = size;
in.args[2].value = value;
request_send(fc, &in, &out);
+ if (out.h.error == -ENOSYS) {
+ fc->no_setxattr = 1;
+ return -EOPNOTSUPP;
+ }
return out.h.error;
}
@@ -810,6 +817,9 @@
struct fuse_getxattr_in inarg;
struct fuse_getxattr_out outarg;
+ if (fc->no_getxattr)
+ return -EOPNOTSUPP;
+
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -833,8 +843,13 @@
request_send(fc, &in, &out);
if (!out.h.error)
return size ? out.args[0].size : outarg.size;
- else
+ else {
+ if (out.h.error == -ENOSYS) {
+ fc->no_getxattr = 1;
+ return -EOPNOTSUPP;
+ }
return out.h.error;
+ }
}
static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
@@ -846,6 +861,9 @@
struct fuse_getxattr_in inarg;
struct fuse_getxattr_out outarg;
+ if (fc->no_listxattr)
+ return -EOPNOTSUPP;
+
memset(&inarg, 0, sizeof(inarg));
inarg.size = size;
@@ -867,8 +885,13 @@
request_send(fc, &in, &out);
if (!out.h.error)
return size ? out.args[0].size : outarg.size;
- else
+ else {
+ if (out.h.error == -ENOSYS) {
+ fc->no_listxattr = 1;
+ return -EOPNOTSUPP;
+ }
return out.h.error;
+ }
}
static int fuse_removexattr(struct dentry *entry, const char *name)
@@ -878,12 +901,19 @@
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
+ if (fc->no_removexattr)
+ return -EOPNOTSUPP;
+
in.h.opcode = FUSE_REMOVEXATTR;
in.h.ino = inode->i_ino;
in.numargs = 1;
in.args[0].size = strlen(name) + 1;
in.args[0].value = name;
request_send(fc, &in, &out);
+ if (out.h.error == -ENOSYS) {
+ fc->no_removexattr = 1;
+ return -EOPNOTSUPP;
+ }
return out.h.error;
}