fix
authorMiklos Szeredi <miklos@szeredi.hu>
Mon, 21 Mar 2005 12:09:04 +0000 (12:09 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Mon, 21 Mar 2005 12:09:04 +0000 (12:09 +0000)
ChangeLog
include/fuse.h
kernel/dir.c
kernel/file.c
kernel/fuse_i.h
kernel/fuse_kernel.h
lib/fuse.c

index 4aa92de746b4b653a9a18e0b9ac77d4dcd635ab4..9ffdbdad74c57aa6dd9a8a751b97119d53030cf2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2005-03-21  Miklos Szeredi <miklos@szeredi.hu>
+
+       * Add fsyncdir() operation
+
 2005-03-19  Miklos Szeredi <miklos@szeredi.hu>
 
        * kernel: add locking to background list (fixes previous fix)
index df6149f5f38d1ddbb48dba99afe5d73786231058..5e5cd4583defaf09e2302090d6f9082e3684dfa3 100644 (file)
@@ -250,6 +250,14 @@ struct fuse_operations {
      */
     int (*opendir) (const char *, struct fuse_file_info *);
 
+    /** Synchronize directory contents
+     *
+     * If the datasync parameter is non-zero, then only the user data
+     * should be flushed, not the meta data.  The fuse_file_info
+     * parameter is currently unused
+     */
+    int (*fsyncdir) (const char *, int, struct fuse_file_info *);
+
     /**
      * Initialize filesystem
      *
index be513093a013591537fdfe34b689940ddd5b4d15..a7507fec834d7a1be2f91d9c1b0dd65d140260d2 100644 (file)
@@ -645,6 +645,11 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
        return fuse_release_common(inode, file, 1);
 }
 
+static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync)
+{
+       return fuse_fsync_common(file, de, datasync, 1);
+}
+
 static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
 {
        unsigned ivalid = iattr->ia_valid;
@@ -1021,6 +1026,7 @@ static struct file_operations fuse_dir_operations = {
        .readdir        = fuse_readdir,
        .open           = fuse_dir_open,
        .release        = fuse_dir_release,
+       .fsync          = fuse_dir_fsync,
 };
 
 static struct inode_operations fuse_common_inode_operations = {
index 74921d63864ff2a59eed2ba2bc42f4219b556f09..0865ab0aed6e4a3864a8cb08837e132eb2f9b2a2 100644 (file)
@@ -151,7 +151,8 @@ static int fuse_flush(struct file *file)
        return err;
 }
 
-static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+                     int isdir)
 {
        struct inode *inode = de->d_inode;
        struct fuse_conn *fc = get_fuse_conn(inode);
@@ -160,7 +161,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        struct fuse_fsync_in inarg;
        int err;
 
-       if (fc->no_fsync)
+       if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
                return 0;
 
        req = fuse_get_request(fc);
@@ -170,7 +171,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
        inarg.fsync_flags = datasync ? 1 : 0;
-       req->in.h.opcode = FUSE_FSYNC;
+       req->in.h.opcode = isdir ? FUSE_FSYNCDIR : FUSE_FSYNC;
        req->in.h.nodeid = get_node_id(inode);
        req->inode = inode;
        req->file = file;
@@ -181,12 +182,20 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        err = req->out.h.error;
        fuse_put_request(fc, req);
        if (err == -ENOSYS) {
-               fc->no_fsync = 1;
+               if (isdir)
+                       fc->no_fsyncdir = 1;
+               else
+                       fc->no_fsync = 1;
                err = 0;
        }
        return err;
 }
 
+static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
+{
+       return fuse_fsync_common(file, de, datasync, 0);
+}
+
 size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
                             struct inode *inode, loff_t pos, size_t count,
                             int isdir)
index d8770718f7b66ab8212d1e6214fbf5e3e760dacc..fb94ebbc36e07ad9b1aae567ba417fe5bda7a27f 100644 (file)
@@ -310,6 +310,9 @@ struct fuse_conn {
        /** Is fsync not implemented by fs? */
        unsigned no_fsync : 1;
 
+       /** Is fsyncdir not implemented by fs? */
+       unsigned no_fsyncdir : 1;
+
        /** Is flush not implemented by fs? */
        unsigned no_flush : 1;
 
@@ -407,6 +410,12 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir);
  */
 int fuse_release_common(struct inode *inode, struct file *file, int isdir);
 
+/** 
+ * Send FSYNC or FSYNCDIR request
+ */
+int fuse_fsync_common(struct file *file, struct dentry *de, int datasync,
+                     int isdir);
+
 /**
  * Initialise file operations on a regular file
  */
index 870ce5974f42218d79a6748698ab7a952cdf924b..2f313eb872c8abda7cacba4ed2622463567f6fc0 100644 (file)
@@ -87,7 +87,8 @@ enum fuse_opcode {
        FUSE_INIT          = 26,
        FUSE_OPENDIR       = 27,
        FUSE_READDIR       = 28,
-       FUSE_RELEASEDIR    = 29
+       FUSE_RELEASEDIR    = 29,
+       FUSE_FSYNCDIR      = 30
 };
 
 /* Conservative buffer size for the client */
index b1aab25a6384905f6d064ba5510c3cb9ebe5ea3e..9694239fd41f5ebc1d76a7ca26dc48362d0c49e9 100644 (file)
@@ -103,6 +103,7 @@ static const char *opname(enum fuse_opcode opcode)
     case FUSE_OPENDIR:         return "OPENDIR";
     case FUSE_READDIR:         return "READDIR";
     case FUSE_RELEASEDIR:      return "RELEASEDIR";
+    case FUSE_FSYNCDIR:                return "FSYNCDIR";
     default:                   return "???";
     }
 }
@@ -1598,6 +1599,24 @@ static void do_releasedir(struct fuse *f, struct fuse_in_header *in,
     send_reply(f, in, 0, NULL, 0);
 }
 
+static void do_fsyncdir(struct fuse *f, struct fuse_in_header *in,
+                        struct fuse_fsync_in *inarg)
+{
+    int res;
+    char *path;
+    struct fuse_file_info fi;
+
+    memset(&fi, 0, sizeof(fi));
+    res = -ENOENT;
+    path = get_path(f, in->nodeid);
+    if (path != NULL) {
+        res = -ENOSYS;
+        if (f->op.fsyncdir)
+            res = f->op.fsyncdir(path, inarg->fsync_flags & 1, &fi);
+        free(path);
+    }
+    send_reply(f, in, res, NULL, 0);
+}
 
 static void free_cmd(struct fuse_cmd *cmd)
 {
@@ -1741,6 +1760,10 @@ void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
         do_releasedir(f, in, (struct fuse_release_in *) inarg);
         break;
 
+    case FUSE_FSYNCDIR:
+        do_fsyncdir(f, in, (struct fuse_fsync_in *) inarg);
+        break;
+
     default:
         send_reply(f, in, -ENOSYS, NULL, 0);
     }