Commit 82547981 authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Linus Torvalds

[PATCH] FUSE: add fsync operation for directories

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: default avatarMiklos Szeredi <miklos@szeredi.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b36c31ba
...@@ -617,6 +617,12 @@ static int fuse_dir_release(struct inode *inode, struct file *file) ...@@ -617,6 +617,12 @@ static int fuse_dir_release(struct inode *inode, struct file *file)
return fuse_release_common(inode, file, 1); 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) static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
{ {
unsigned ivalid = iattr->ia_valid; unsigned ivalid = iattr->ia_valid;
...@@ -934,6 +940,7 @@ static struct file_operations fuse_dir_operations = { ...@@ -934,6 +940,7 @@ static struct file_operations fuse_dir_operations = {
.readdir = fuse_readdir, .readdir = fuse_readdir,
.open = fuse_dir_open, .open = fuse_dir_open,
.release = fuse_dir_release, .release = fuse_dir_release,
.fsync = fuse_dir_fsync,
}; };
static struct inode_operations fuse_common_inode_operations = { static struct inode_operations fuse_common_inode_operations = {
......
...@@ -156,7 +156,8 @@ static int fuse_flush(struct file *file) ...@@ -156,7 +156,8 @@ static int fuse_flush(struct file *file)
return err; 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 inode *inode = de->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_conn *fc = get_fuse_conn(inode);
...@@ -165,7 +166,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) ...@@ -165,7 +166,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
struct fuse_fsync_in inarg; struct fuse_fsync_in inarg;
int err; int err;
if (fc->no_fsync) if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
return 0; return 0;
req = fuse_get_request(fc); req = fuse_get_request(fc);
...@@ -175,7 +176,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) ...@@ -175,7 +176,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
memset(&inarg, 0, sizeof(inarg)); memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh; inarg.fh = ff->fh;
inarg.fsync_flags = datasync ? 1 : 0; 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->in.h.nodeid = get_node_id(inode);
req->inode = inode; req->inode = inode;
req->file = file; req->file = file;
...@@ -186,12 +187,20 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) ...@@ -186,12 +187,20 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
err = req->out.h.error; err = req->out.h.error;
fuse_put_request(fc, req); fuse_put_request(fc, req);
if (err == -ENOSYS) { if (err == -ENOSYS) {
fc->no_fsync = 1; if (isdir)
fc->no_fsyncdir = 1;
else
fc->no_fsync = 1;
err = 0; err = 0;
} }
return err; 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, size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
struct inode *inode, loff_t pos, size_t count, struct inode *inode, loff_t pos, size_t count,
int isdir) int isdir)
......
...@@ -248,6 +248,9 @@ struct fuse_conn { ...@@ -248,6 +248,9 @@ struct fuse_conn {
/** Is fsync not implemented by fs? */ /** Is fsync not implemented by fs? */
unsigned no_fsync : 1; unsigned no_fsync : 1;
/** Is fsyncdir not implemented by fs? */
unsigned no_fsyncdir : 1;
/** Is flush not implemented by fs? */ /** Is flush not implemented by fs? */
unsigned no_flush : 1; unsigned no_flush : 1;
...@@ -339,6 +342,12 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir); ...@@ -339,6 +342,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); 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 * Initialise file operations on a regular file
*/ */
......
...@@ -99,7 +99,8 @@ enum fuse_opcode { ...@@ -99,7 +99,8 @@ enum fuse_opcode {
FUSE_INIT = 26, FUSE_INIT = 26,
FUSE_OPENDIR = 27, FUSE_OPENDIR = 27,
FUSE_READDIR = 28, FUSE_READDIR = 28,
FUSE_RELEASEDIR = 29 FUSE_RELEASEDIR = 29,
FUSE_FSYNCDIR = 30
}; };
/* Conservative buffer size for the client */ /* Conservative buffer size for the client */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment