* 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>
 
 
     read:      xmp_read,
     write:     xmp_write,
     statfs:    xmp_statfs,
-    release:   NULL
+    release:   NULL,
+    fsync:     NULL
+    
 };
 
 int main(int argc, char *argv[])
 
     read:      hello_read,
     write:     NULL,
     statfs:    NULL,
-    release:   NULL
+    release:   NULL,
+    fsync:     NULL
 };
 
 int main(int argc, char *argv[])
 
 #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)
 {
     read:      null_read,
     write:     null_write,
     statfs:    null_statfs,
-    release:   NULL
+    release:   NULL,
+    fsync:     NULL
 };
 
 int main(int argc, char *argv[])
 
  *       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 *);
     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 */
 
        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 */
        struct fuse_kstatfs st;
 };
 
+struct fuse_fsync_in {
+       int datasync;
+};
+
 struct fuse_in_header {
        int unique;
        enum fuse_opcode opcode;
 
 
 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)
 
     case FUSE_WRITE:    return "WRITE";
     case FUSE_STATFS:   return "STATFS";
     case FUSE_RELEASE:  return "RELEASE";
+    case FUSE_FSYNC:    return "FSYNC";
     default:            return "???";
     }
 }
     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);
         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);
     }