diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2014-10-07 17:15:23 +0200 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2014-10-07 17:15:23 +0200 |
commit | d59a3a41d3363eb96d7f827645bdd93d3b308563 (patch) | |
tree | 55c01ed0af99249a0eeb474300e15c30c0964674 | |
parent | e3b7d4c278a26520be63d99d6ea84b26906fe73d (diff) | |
download | fuse-sync_release.tar.gz |
Add support for -osync_releasesync_release
-rw-r--r-- | include/fuse_common.h | 9 | ||||
-rw-r--r-- | include/fuse_kernel.h | 12 | ||||
-rw-r--r-- | lib/fuse.c | 37 | ||||
-rwxr-xr-x | lib/fuse_lowlevel.c | 7 |
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 @@ -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 |