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 <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
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)
{
unsigned ivalid = iattr->ia_valid;
static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
{
unsigned ivalid = iattr->ia_valid;
.readdir = fuse_readdir,
.open = fuse_dir_open,
.release = fuse_dir_release,
.readdir = fuse_readdir,
.open = fuse_dir_open,
.release = fuse_dir_release,
+ .fsync = fuse_dir_fsync,
};
static struct inode_operations fuse_common_inode_operations = {
};
static struct inode_operations fuse_common_inode_operations = {
-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);
{
struct inode *inode = de->d_inode;
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_fsync_in inarg;
int err;
struct fuse_fsync_in inarg;
int err;
+ if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir))
return 0;
req = fuse_get_request(fc);
return 0;
req = fuse_get_request(fc);
memset(&inarg, 0, sizeof(inarg));
inarg.fh = ff->fh;
inarg.fsync_flags = datasync ? 1 : 0;
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;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->file = file;
err = req->out.h.error;
fuse_put_request(fc, req);
if (err == -ENOSYS) {
err = req->out.h.error;
fuse_put_request(fc, req);
if (err == -ENOSYS) {
+ if (isdir)
+ fc->no_fsyncdir = 1;
+ else
+ fc->no_fsync = 1;
+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)
size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
struct inode *inode, loff_t pos, size_t count,
int isdir)
/** Is fsync not implemented by fs? */
unsigned no_fsync : 1;
/** 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;
/** Is flush not implemented by fs? */
unsigned no_flush : 1;
*/
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
*/
FUSE_INIT = 26,
FUSE_OPENDIR = 27,
FUSE_READDIR = 28,
FUSE_INIT = 26,
FUSE_OPENDIR = 27,
FUSE_READDIR = 28,
+ FUSE_RELEASEDIR = 29,
+ FUSE_FSYNCDIR = 30
};
/* Conservative buffer size for the client */
};
/* Conservative buffer size for the client */