From: Miklos Szeredi This patch adds a new FSYNCDIR request, which is sent when fsync is called on directories. This operation is available in libfuse 2.3-pre1 or greater. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton --- fs/fuse/dir.c | 7 +++++++ fs/fuse/file.c | 17 +++++++++++++---- fs/fuse/fuse_i.h | 9 +++++++++ include/linux/fuse.h | 3 ++- 4 files changed, 31 insertions(+), 5 deletions(-) diff -puN fs/fuse/dir.c~fuse-add-fsync-operation-for-directories fs/fuse/dir.c --- 25/fs/fuse/dir.c~fuse-add-fsync-operation-for-directories 2005-06-21 01:43:05.000000000 -0700 +++ 25-akpm/fs/fuse/dir.c 2005-06-21 01:43:08.000000000 -0700 @@ -615,6 +615,12 @@ static int fuse_dir_release(struct inode return fuse_release_common(inode, file, 1); } +static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) +{ + /* nfsd can call this with no file */ + return file ? fuse_fsync_common(file, de, datasync, 1) : 0; +} + static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) { unsigned ivalid = iattr->ia_valid; @@ -932,6 +938,7 @@ static struct file_operations fuse_dir_o .readdir = fuse_readdir, .open = fuse_dir_open, .release = fuse_dir_release, + .fsync = fuse_dir_fsync, }; static struct inode_operations fuse_common_inode_operations = { diff -puN fs/fuse/file.c~fuse-add-fsync-operation-for-directories fs/fuse/file.c --- 25/fs/fuse/file.c~fuse-add-fsync-operation-for-directories 2005-06-21 01:43:05.000000000 -0700 +++ 25-akpm/fs/fuse/file.c 2005-06-21 01:43:05.000000000 -0700 @@ -152,7 +152,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); @@ -161,7 +162,7 @@ static int fuse_fsync(struct file *file, 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); @@ -171,7 +172,7 @@ static int fuse_fsync(struct file *file, 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; @@ -182,12 +183,20 @@ static int fuse_fsync(struct file *file, 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) diff -puN fs/fuse/fuse_i.h~fuse-add-fsync-operation-for-directories fs/fuse/fuse_i.h --- 25/fs/fuse/fuse_i.h~fuse-add-fsync-operation-for-directories 2005-06-21 01:43:05.000000000 -0700 +++ 25-akpm/fs/fuse/fuse_i.h 2005-06-21 01:43:05.000000000 -0700 @@ -254,6 +254,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; @@ -346,6 +349,12 @@ int fuse_open_common(struct inode *inode 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 */ void fuse_init_file_inode(struct inode *inode); diff -puN include/linux/fuse.h~fuse-add-fsync-operation-for-directories include/linux/fuse.h --- 25/include/linux/fuse.h~fuse-add-fsync-operation-for-directories 2005-06-21 01:43:05.000000000 -0700 +++ 25-akpm/include/linux/fuse.h 2005-06-21 01:43:05.000000000 -0700 @@ -90,7 +90,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 */ _