mirror of https://gitee.com/openkylin/linux.git
[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: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
b36c31ba95
commit
8254798199
|
@ -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 = {
|
||||||
.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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 {
|
||||||
/** 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);
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue