aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--kernel/fuse_kernel.h10
-rw-r--r--lib/fuse.c28
-rw-r--r--lib/fuse_lowlevel.c4
4 files changed, 34 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 0478639..1234576 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2006-10-01 Miklos Szeredi <miklos@szeredi.hu>
+ * Add support for FLUSH+RELEASE operation for FreeBSD. Original
+ patch by Csaba Henk
+
* Add init script to insert fuse module and mount the control
filesystem. The script is installed as /etc/init.d/fuse and on
debian based systems (where update-rc.d is available) symlinks
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index c2243d9..94154b1 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -50,7 +50,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 7
+#define FUSE_KERNEL_MINOR_VERSION 8
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -127,6 +127,11 @@ struct fuse_file_lock {
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
+/**
+ * Release flags
+ */
+#define FUSE_RELEASE_FLUSH (1 << 0)
+
enum fuse_opcode {
FUSE_LOOKUP = 1,
FUSE_FORGET = 2, /* no reply */
@@ -241,7 +246,8 @@ struct fuse_open_out {
struct fuse_release_in {
__u64 fh;
__u32 flags;
- __u32 padding;
+ __u32 release_flags;
+ __u64 lock_owner;
};
struct fuse_flush_in {
diff --git a/lib/fuse.c b/lib/fuse.c
index c28528e..c87bff3 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -583,6 +583,17 @@ static int fuse_do_open(struct fuse *f, fuse_req_t req, char *path,
return res;
}
+static int fuse_do_flush(struct fuse *f, fuse_req_t req, const char *path,
+ struct fuse_file_info *fi)
+{
+ int res;
+ struct fuse_intr_data d;
+ fuse_prepare_interrupt(f, req, &d);
+ res = f->op.flush(path, fi);
+ fuse_finish_interrupt(f, req, &d);
+ return res;
+}
+
static int fuse_do_statfs(struct fuse *f, fuse_req_t req, const char *path,
struct statvfs *buf)
{
@@ -1628,14 +1639,17 @@ static void fuse_release(fuse_req_t req, fuse_ino_t ino,
char *path;
struct node *node;
int unlink_hidden = 0;
+ int err = 0;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
if (f->conf.debug) {
- printf("RELEASE[%llu] flags: 0x%x\n", (unsigned long long) fi->fh,
- fi->flags);
+ printf("RELEASE%s[%llu] flags: 0x%x\n", fi->flush ? "+FLUSH" : "",
+ (unsigned long long) fi->fh, fi->flags);
fflush(stdout);
}
+ if (fi->flush && path && f->op.flush)
+ err = fuse_do_flush(f, req, path, fi);
if (f->op.release)
fuse_compat_release(f, req, path, fi);
@@ -1656,7 +1670,7 @@ static void fuse_release(fuse_req_t req, fuse_ino_t ino,
free(path);
pthread_rwlock_unlock(&f->tree_lock);
- reply_err(req, 0);
+ reply_err(req, err);
}
static void fuse_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
@@ -2277,12 +2291,8 @@ static void fuse_flush(fuse_req_t req, fuse_ino_t ino,
fflush(stdout);
}
err = -ENOSYS;
- if (f->op.flush) {
- struct fuse_intr_data d;
- fuse_prepare_interrupt(f, req, &d);
- err = f->op.flush(path, fi);
- fuse_finish_interrupt(f, req, &d);
- }
+ if (f->op.flush)
+ err = fuse_do_flush(f, req, path, fi);
free(path);
}
if (f->op.lock) {
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 4308a26..f7de2c7 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -643,6 +643,10 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fi.flags = arg->flags;
fi.fh = arg->fh;
fi.fh_old = fi.fh;
+ if (req->f->conn.proto_minor >= 8) {
+ fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
+ fi.lock_owner = arg->lock_owner;
+ }
if (req->f->op.release)
req->f->op.release(req, nodeid, &fi);