aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-03-21 12:09:04 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2005-03-21 12:09:04 +0000
commit4283ee7760e3fd5146750fc6f039c7db1504e742 (patch)
tree352062213a2e7213c0084753b122214526672770
parentd17da46055903a517274b7823d41fdd866f48d8d (diff)
downloadlibfuse-4283ee7760e3fd5146750fc6f039c7db1504e742.tar.gz
fix
-rw-r--r--ChangeLog4
-rw-r--r--include/fuse.h8
-rw-r--r--kernel/dir.c6
-rw-r--r--kernel/file.c17
-rw-r--r--kernel/fuse_i.h9
-rw-r--r--kernel/fuse_kernel.h3
-rw-r--r--lib/fuse.c23
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 <miklos@szeredi.hu>
+
+ * Add fsyncdir() operation
+
2005-03-19 Miklos Szeredi <miklos@szeredi.hu>
* 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);
}