aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2004-06-03 14:45:04 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2004-06-03 14:45:04 +0000
commit63b8c1c99797322bb873803b0296ac302d5de4d2 (patch)
tree0ed50a9e1a1e0bd45e2c47aa49fc26aec0e56e30
parentff8753578ac425bf64502f6b26c85c5a4cb0d17b (diff)
downloadlibfuse-63b8c1c99797322bb873803b0296ac302d5de4d2.tar.gz
cache ENOSYS on some optional functions
-rw-r--r--ChangeLog3
-rw-r--r--include/fuse.h2
-rw-r--r--kernel/dev.c1
-rw-r--r--kernel/dir.c34
-rw-r--r--kernel/file.c15
-rw-r--r--kernel/fuse_i.h18
-rw-r--r--lib/fuse.c11
7 files changed, 74 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index 3d32987..da590de 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,9 @@
background if mount is successful. '-f' and '-d' options disable
backgrounding. This fixes the "Why does my FUSE daemon hang?"
newbie complaint.
+
+ * Cache ENOSYS (function not implemented) errors on *xattr, flush
+ and fsync
2004-05-18 Miklos Szeredi <mszeredi@inf.bme.hu>
diff --git a/include/fuse.h b/include/fuse.h
index e3e4333..d298cb3 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -103,7 +103,7 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type);
* then set the callback pointer to NULL.
*
* - fsync() has a boolean 'datasync' parameter which if TRUE then do
- * an fdatasync() operation.
+ * an fdatasync() operation. Implementing this call is optional.
*/
struct fuse_operations {
int (*getattr) (const char *, struct stat *);
diff --git a/kernel/dev.c b/kernel/dev.c
index afc9f4c..af20de8 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -543,6 +543,7 @@ static struct fuse_conn *new_conn(void)
fc = kmalloc(sizeof(*fc), GFP_KERNEL);
if (fc != NULL) {
+ memset(fc, 0, sizeof(*fc));
fc->sb = NULL;
fc->file = NULL;
fc->flags = 0;
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 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
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 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
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 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
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 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
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 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
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 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
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 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
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;
}
diff --git a/kernel/file.c b/kernel/file.c
index c9a44fd..2067bd7 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -99,11 +99,16 @@ static int fuse_flush(struct file *file)
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
+ if (fc->no_flush)
+ return 0;
+
in.h.opcode = FUSE_FLUSH;
in.h.ino = inode->i_ino;
request_send(fc, &in, &out);
- if (out.h.error == -ENOSYS)
+ if (out.h.error == -ENOSYS) {
+ fc->no_flush = 1;
return 0;
+ }
else
return out.h.error;
}
@@ -116,6 +121,9 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
struct fuse_out out = FUSE_OUT_INIT;
struct fuse_fsync_in inarg;
+ if (fc->no_fsync)
+ return 0;
+
memset(&inarg, 0, sizeof(inarg));
inarg.datasync = datasync;
@@ -125,6 +133,11 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
in.args[0].size = sizeof(inarg);
in.args[0].value = &inarg;
request_send(fc, &in, &out);
+
+ if (out.h.error == -ENOSYS) {
+ fc->no_fsync = 1;
+ return 0;
+ }
return out.h.error;
/* FIXME: need to ensure, that all write requests issued
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 1299139..d5943a9 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -96,6 +96,24 @@ struct fuse_conn {
/** The next unique request id */
int reqctr;
+
+ /** Is fsync not implemented by fs? */
+ unsigned int no_fsync : 1;
+
+ /** Is flush not implemented by fs? */
+ unsigned int no_flush : 1;
+
+ /** Is setxattr not implemented by fs? */
+ unsigned int no_setxattr : 1;
+
+ /** Is getxattr not implemented by fs? */
+ unsigned int no_getxattr : 1;
+
+ /** Is listxattr not implemented by fs? */
+ unsigned int no_listxattr : 1;
+
+ /** Is removexattr not implemented by fs? */
+ unsigned int no_removexattr : 1;
};
/** One input argument of a request */
diff --git a/lib/fuse.c b/lib/fuse.c
index 255a24b..05d9713 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -980,8 +980,7 @@ static void do_fsync(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if(path != NULL) {
- /* fsync is not mandatory, so don't return ENOSYS */
- res = 0;
+ res = -ENOSYS;
if(f->op.fsync)
res = f->op.fsync(path, inarg->datasync);
free(path);
@@ -1000,7 +999,7 @@ static void do_setxattr(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if (path != NULL) {
- res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+ res = -ENOSYS;
if (f->op.setxattr)
res = f->op.setxattr(path, name, value, arg->size, arg->flags);
free(path);
@@ -1017,7 +1016,7 @@ static int common_getxattr(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if (path != NULL) {
- res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+ res = -ENOSYS;
if (f->op.getxattr)
res = f->op.getxattr(path, name, value, size);
free(path);
@@ -1081,7 +1080,7 @@ static int common_listxattr(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if (path != NULL) {
- res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+ res = -ENOSYS;
if (f->op.listxattr)
res = f->op.listxattr(path, list, size);
free(path);
@@ -1142,7 +1141,7 @@ static void do_removexattr(struct fuse *f, struct fuse_in_header *in,
res = -ENOENT;
path = get_path(f, in->ino);
if (path != NULL) {
- res = -EOPNOTSUPP; /* or is it ENOTSUPP ??? */
+ res = -ENOSYS;
if (f->op.removexattr)
res = f->op.removexattr(path, name);
free(path);