added fsync operation
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 @@
     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 @@
     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 @@
     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 @@
  *       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 @@
     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 @@
 	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_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_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 @@
     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 @@
     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 @@
         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);
     }