summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@suse.cz>2014-10-07 17:15:23 +0200
committerMiklos Szeredi <mszeredi@suse.cz>2014-10-07 17:15:23 +0200
commitd59a3a41d3363eb96d7f827645bdd93d3b308563 (patch)
tree55c01ed0af99249a0eeb474300e15c30c0964674
parente3b7d4c278a26520be63d99d6ea84b26906fe73d (diff)
downloadfuse-sync_release.tar.gz
Add support for -osync_releasesync_release
-rw-r--r--include/fuse_common.h9
-rw-r--r--include/fuse_kernel.h12
-rw-r--r--lib/fuse.c37
-rwxr-xr-xlib/fuse_lowlevel.c7
4 files changed, 59 insertions, 6 deletions
diff --git a/include/fuse_common.h b/include/fuse_common.h
index aec4349..fd0dc57 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -67,8 +67,15 @@ struct fuse_file_info {
2.9 */
unsigned int flock_release : 1;
+ /**
+ * Can be filled in by open to indicate that the kernel should
+ * try releasing the file synchronously. Introduced in 3.0
+ */
+ unsigned int sync_release : 1;
+
/** Padding. Do not use*/
- unsigned int padding : 27;
+ unsigned int padding : 25;
+ unsigned int padding1 : 32;
/** File handle. May be filled in by filesystem in open().
Available in all other file operations */
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index 40b5ca8..f266c1a 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -101,6 +101,11 @@
* - add FATTR_CTIME
* - add ctime and ctimensec to fuse_setattr_in
* - add FUSE_RENAME2 request
+ * - add FUSE_NO_OPEN_SUPPORT flag
+ *
+ * 7.24
+ * - add FOPEN_SYNC_RELEASE open flag
+ * - add FUSE_RELEASE_ISSYNC release flag
*/
#ifndef _LINUX_FUSE_H
@@ -136,7 +141,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 23
+#define FUSE_KERNEL_MINOR_VERSION 24
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -204,10 +209,12 @@ struct fuse_file_lock {
* FOPEN_DIRECT_IO: bypass page cache for this open file
* FOPEN_KEEP_CACHE: don't invalidate the data cache on open
* FOPEN_NONSEEKABLE: the file is not seekable
+ * FOPEN_SYNC_RELEASE: try synchronous release
*/
#define FOPEN_DIRECT_IO (1 << 0)
#define FOPEN_KEEP_CACHE (1 << 1)
#define FOPEN_NONSEEKABLE (1 << 2)
+#define FOPEN_SYNC_RELEASE (1 << 3)
/**
* INIT request/reply flags
@@ -229,6 +236,7 @@ struct fuse_file_lock {
* FUSE_READDIRPLUS_AUTO: adaptive readdirplus
* FUSE_ASYNC_DIO: asynchronous direct I/O submission
* FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes
+ * FUSE_NO_OPEN_SUPPORT: kernel supports zero-message opens
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -247,6 +255,7 @@ struct fuse_file_lock {
#define FUSE_READDIRPLUS_AUTO (1 << 14)
#define FUSE_ASYNC_DIO (1 << 15)
#define FUSE_WRITEBACK_CACHE (1 << 16)
+#define FUSE_NO_OPEN_SUPPORT (1 << 17)
/**
* CUSE INIT request/reply flags
@@ -260,6 +269,7 @@ struct fuse_file_lock {
*/
#define FUSE_RELEASE_FLUSH (1 << 0)
#define FUSE_RELEASE_FLOCK_UNLOCK (1 << 1)
+#define FUSE_RELEASE_ISSYNC (1 << 2)
/**
* Getattr flags
diff --git a/lib/fuse.c b/lib/fuse.c
index 75d657c..f4acd32 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -75,6 +75,8 @@ struct fuse_config {
int direct_io;
int kernel_cache;
int auto_cache;
+ int sync_release;
+ int nosync_release;
int intr;
int intr_signal;
int help;
@@ -1640,9 +1642,10 @@ int fuse_fs_release(struct fuse_fs *fs, const char *path,
fuse_get_context()->private_data = fs->user_data;
if (fs->op.release) {
if (fs->debug)
- fprintf(stderr, "release%s[%llu] flags: 0x%x\n",
+ fprintf(stderr, "release%s[%llu] flags: 0x%x%s\n",
fi->flush ? "+flush" : "",
- (unsigned long long) fi->fh, fi->flags);
+ (unsigned long long) fi->fh, fi->flags,
+ fi->sync_release ? " (sync)" : "");
return fs->op.release(path, fi);
} else {
@@ -1920,8 +1923,9 @@ int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
fuse_get_context()->private_data = fs->user_data;
if (fs->op.releasedir) {
if (fs->debug)
- fprintf(stderr, "releasedir[%llu] flags: 0x%x\n",
- (unsigned long long) fi->fh, fi->flags);
+ fprintf(stderr, "releasedir[%llu] flags: 0x%x%s\n",
+ (unsigned long long) fi->fh, fi->flags,
+ fi->sync_release ? " (sync)" : "");
return fs->op.releasedir(path, fi);
} else {
@@ -2838,6 +2842,11 @@ static void fuse_lib_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
fi.flags = O_CREAT | O_EXCL | O_WRONLY;
err = fuse_fs_create(f->fs, path, mode, &fi);
if (!err) {
+ if (f->conf.sync_release)
+ fi.sync_release = 1;
+ if (f->conf.nosync_release)
+ fi.sync_release = 0;
+
err = lookup_path(f, parent, name, path, &e,
&fi);
fuse_fs_release(f->fs, path, &fi);
@@ -3066,6 +3075,10 @@ static void fuse_lib_create(fuse_req_t req, fuse_ino_t parent,
} else {
if (f->conf.direct_io)
fi->direct_io = 1;
+ if (f->conf.sync_release)
+ fi->sync_release = 1;
+ if (f->conf.nosync_release)
+ fi->sync_release = 0;
if (f->conf.kernel_cache)
fi->keep_cache = 1;
@@ -3143,6 +3156,10 @@ static void fuse_lib_open(fuse_req_t req, fuse_ino_t ino,
if (!err) {
if (f->conf.direct_io)
fi->direct_io = 1;
+ if (f->conf.sync_release)
+ fi->sync_release = 1;
+ if (f->conf.nosync_release)
+ fi->sync_release = 0;
if (f->conf.kernel_cache)
fi->keep_cache = 1;
@@ -3277,6 +3294,13 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
if (!err) {
fuse_prepare_interrupt(f, req, &d);
err = fuse_fs_opendir(f->fs, path, &fi);
+ if (!err) {
+ llfi->sync_release = fi.sync_release;
+ if (f->conf.sync_release)
+ llfi->sync_release = 1;
+ if (f->conf.nosync_release)
+ llfi->sync_release = 0;
+ }
fuse_finish_interrupt(f, req, &d);
dh->fh = fi.fh;
}
@@ -3630,6 +3654,8 @@ static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
struct fuse_dh *dh = get_dirhandle(llfi, &fi);
char *path;
+ fi.sync_release = llfi->sync_release;
+
get_path_nullok(f, ino, &path);
fuse_prepare_interrupt(f, req, &d);
@@ -4422,6 +4448,8 @@ static const struct fuse_opt fuse_lib_opts[] = {
FUSE_LIB_OPT("kernel_cache", kernel_cache, 1),
FUSE_LIB_OPT("auto_cache", auto_cache, 1),
FUSE_LIB_OPT("noauto_cache", auto_cache, 0),
+ FUSE_LIB_OPT("sync_release", sync_release, 1),
+ FUSE_LIB_OPT("nosync_release", nosync_release, 1),
FUSE_LIB_OPT("umask=", set_mode, 1),
FUSE_LIB_OPT("umask=%o", umask, 0),
FUSE_LIB_OPT("uid=", set_uid, 1),
@@ -4451,6 +4479,7 @@ static void fuse_lib_help(void)
" -o direct_io use direct I/O\n"
" -o kernel_cache cache files in kernel\n"
" -o [no]auto_cache enable caching based on modification times (off)\n"
+" -o [no]sync_release enable synchronous release\n"
" -o umask=M set file permissions (octal)\n"
" -o uid=N set file owner\n"
" -o gid=N set file group\n"
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 1911863..fce7972 100755
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -440,6 +440,8 @@ static void fill_open(struct fuse_open_out *arg,
arg->open_flags |= FOPEN_KEEP_CACHE;
if (f->nonseekable)
arg->open_flags |= FOPEN_NONSEEKABLE;
+ if (f->sync_release)
+ arg->open_flags |= FOPEN_SYNC_RELEASE;
}
int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
@@ -1454,6 +1456,8 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fi.flock_release = 1;
fi.lock_owner = arg->lock_owner;
}
+ if (arg->release_flags & FUSE_RELEASE_ISSYNC)
+ fi.sync_release = 1;
if (req->f->op.release)
req->f->op.release(req, nodeid, &fi);
@@ -1526,6 +1530,9 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fi.flags = arg->flags;
fi.fh = arg->fh;
+ if (arg->release_flags & FUSE_RELEASE_ISSYNC)
+ fi.sync_release = 1;
+
if (req->f->op.releasedir)
req->f->op.releasedir(req, nodeid, &fi);
else