From 4283ee7760e3fd5146750fc6f039c7db1504e742 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 21 Mar 2005 12:09:04 +0000 Subject: [PATCH] fix --- ChangeLog | 4 ++++ include/fuse.h | 8 ++++++++ kernel/dir.c | 6 ++++++ kernel/file.c | 17 +++++++++++++---- kernel/fuse_i.h | 9 +++++++++ kernel/fuse_kernel.h | 3 ++- lib/fuse.c | 23 +++++++++++++++++++++++ 7 files changed, 65 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4aa92de..9ffdbda 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-03-21 Miklos Szeredi + + * Add fsyncdir() operation + 2005-03-19 Miklos Szeredi * kernel: add locking to background list (fixes previous fix) diff --git a/include/fuse.h b/include/fuse.h index df6149f..5e5cd45 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -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 * diff --git a/kernel/dir.c b/kernel/dir.c index be51309..a7507fe 100644 --- a/kernel/dir.c +++ b/kernel/dir.c @@ -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 = { diff --git a/kernel/file.c b/kernel/file.c index 74921d6..0865ab0 100644 --- a/kernel/file.c +++ b/kernel/file.c @@ -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) diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h index d877071..fb94ebb 100644 --- a/kernel/fuse_i.h +++ b/kernel/fuse_i.h @@ -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 */ diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h index 870ce59..2f313eb 100644 --- a/kernel/fuse_kernel.h +++ b/kernel/fuse_kernel.h @@ -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 */ diff --git a/lib/fuse.c b/lib/fuse.c index b1aab25..9694239 100644 --- a/lib/fuse.c +++ b/lib/fuse.c @@ -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); } -- 2.30.2