aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog2
-rw-r--r--example/fusexmp.c4
-rw-r--r--example/hello.c3
-rw-r--r--example/null.c5
-rw-r--r--include/fuse.h5
-rw-r--r--include/linux/fuse.h7
-rw-r--r--kernel/file.c17
-rw-r--r--lib/fuse.c23
8 files changed, 58 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index ae9fdbb..15efcd3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,7 +2,7 @@
* Make it compile on 2.4.19.
- * Add dummy fsync operation (write file failed on xemacs & vi)
+ * Add fsync operation (write file failed on xemacs & vi)
2003-12-12 David McNab <david@rebirthing.co.nz>
diff --git a/example/fusexmp.c b/example/fusexmp.c
index e783423..d97f3ca 100644
--- a/example/fusexmp.c
+++ b/example/fusexmp.c
@@ -267,7 +267,9 @@ static struct fuse_operations xmp_oper = {
read: xmp_read,
write: xmp_write,
statfs: xmp_statfs,
- release: NULL
+ release: NULL,
+ fsync: NULL
+
};
int main(int argc, char *argv[])
diff --git a/example/hello.c b/example/hello.c
index cd8fb5d..6b461d0 100644
--- a/example/hello.c
+++ b/example/hello.c
@@ -86,7 +86,8 @@ static struct fuse_operations hello_oper = {
read: hello_read,
write: NULL,
statfs: NULL,
- release: NULL
+ release: NULL,
+ fsync: NULL
};
int main(int argc, char *argv[])
diff --git a/example/null.c b/example/null.c
index b712b5c..ca79dc4 100644
--- a/example/null.c
+++ b/example/null.c
@@ -12,7 +12,7 @@
#include <time.h>
#include <errno.h>
-#define UNUSED __attribute__((unused))
+#define UNUSED(x) x __attribute__((unused))
static int null_getattr(const char *path, struct stat *stbuf)
{
@@ -89,7 +89,8 @@ static struct fuse_operations null_oper = {
read: null_read,
write: null_write,
statfs: null_statfs,
- release: NULL
+ release: NULL,
+ fsync: NULL
};
int main(int argc, char *argv[])
diff --git a/include/fuse.h b/include/fuse.h
index 719564e..59e0ed1 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -87,7 +87,9 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type);
* 2) all memory mappings unmapped
* This call need only be implemented if this information is required,
* otherwise set this function to NULL.
- *
+ *
+ * - fsync() has a boolean 'datasync' parameter which if TRUE then do
+ * an fdatasync() operation.
*/
struct fuse_operations {
int (*getattr) (const char *, struct stat *);
@@ -109,6 +111,7 @@ struct fuse_operations {
int (*write) (const char *, const char *, size_t, off_t);
int (*statfs) (struct fuse_statfs *);
int (*release) (const char *, int);
+ int (*fsync) (const char *, int);
};
/** Extra context that may be needed by some filesystems */
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 4be9a28..08ad214 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -103,7 +103,8 @@ enum fuse_opcode {
FUSE_WRITE = 16,
FUSE_STATFS = 17,
FUSE_RELEASE = 18, /* no reply */
- FUSE_INVALIDATE = 19 /* user initiated */
+ FUSE_INVALIDATE = 19, /* user initiated */
+ FUSE_FSYNC = 20
};
/* Conservative buffer size for the client */
@@ -176,6 +177,10 @@ struct fuse_statfs_out {
struct fuse_kstatfs st;
};
+struct fuse_fsync_in {
+ int datasync;
+};
+
struct fuse_in_header {
int unique;
enum fuse_opcode opcode;
diff --git a/kernel/file.c b/kernel/file.c
index ca4440c..11e7bc0 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -74,7 +74,22 @@ static int fuse_release(struct inode *inode, struct file *file)
static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
{
- return 0;
+ struct inode *inode = de->d_inode;
+ struct fuse_conn *fc = INO_FC(inode);
+ struct fuse_in in = FUSE_IN_INIT;
+ struct fuse_out out = FUSE_OUT_INIT;
+ struct fuse_fsync_in inarg;
+
+ memset(&inarg, 0, sizeof(inarg));
+ inarg.datasync = datasync;
+
+ in.h.opcode = FUSE_FSYNC;
+ in.h.ino = inode->i_ino;
+ in.numargs = 1;
+ in.args[0].size = sizeof(inarg);
+ in.args[0].value = &inarg;
+ request_send(fc, &in, &out);
+ return out.h.error;
}
static int fuse_readpage(struct file *file, struct page *page)
diff --git a/lib/fuse.c b/lib/fuse.c
index d0537fc..d382707 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -40,6 +40,7 @@ static const char *opname(enum fuse_opcode opcode)
case FUSE_WRITE: return "WRITE";
case FUSE_STATFS: return "STATFS";
case FUSE_RELEASE: return "RELEASE";
+ case FUSE_FSYNC: return "FSYNC";
default: return "???";
}
}
@@ -866,6 +867,24 @@ static void do_statfs(struct fuse *f, struct fuse_in_header *in)
send_reply(f, in, res, &arg, sizeof(arg));
}
+static void do_fsync(struct fuse *f, struct fuse_in_header *in,
+ struct fuse_fsync_in *inarg)
+{
+ int res;
+ char *path;
+
+ res = -ENOENT;
+ path = get_path(f, in->ino);
+ if(path != NULL) {
+ /* fsync is not mandatory, so don't return ENOSYS */
+ res = 0;
+ if(f->op.fsync)
+ res = f->op.fsync(path, inarg->datasync);
+ free(path);
+ }
+ send_reply(f, in, res, NULL, 0);
+}
+
static void free_cmd(struct fuse_cmd *cmd)
{
free(cmd->buf);
@@ -960,6 +979,10 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
do_statfs(f, in);
break;
+ case FUSE_FSYNC:
+ do_fsync(f, in, (struct fuse_fsync_in *) inarg);
+ break;
+
default:
send_reply(f, in, -ENOSYS, NULL, 0);
}