libfuse: add "time_gran" option
authorMiklos Szeredi <mszeredi@suse.cz>
Tue, 15 Jul 2014 15:11:08 +0000 (17:11 +0200)
committerMiklos Szeredi <mszeredi@suse.cz>
Tue, 15 Jul 2014 15:36:43 +0000 (17:36 +0200)
This allows the filesystem to specify the time granularity it
supports when the kernel is responsible for updating times
("writeback_cache" option).

ChangeLog
include/fuse_common.h
include/fuse_kernel.h
lib/fuse_lowlevel.c

index fd3acd5980e0823066c3f09ee9d8b478df7ce2ed..167ca7e5919f0deb287a33afa613b91fabecdfba 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,10 @@
        result in EINVAL when mounting the filesystem.  This also needs a
        fix in the kernel.
 
+       * libfuse: add "time_gran" option.  This allows the filesystem to
+       specify the time granularity it supports when the kernel is
+       responsible for updating times ("writeback_cache" option).
+
 2014-03-26  Miklos Szeredi <miklos@szeredi.hu>
 
        * Initilaize stat buffer passed to ->getattr() and ->fgetattr() to
index 22d9591bc9e2cb8668b2907bf84fecd20c000874..aec4349c60ab4297258feefe738f23781ef7b561 100644 (file)
@@ -189,10 +189,18 @@ struct fuse_conn_info {
         */
        unsigned congestion_threshold;
 
+       /**
+        * Time granularity if kernel is responsible for setting times (in nsec)
+        *
+        * Should be power of 10.  A zero (default) value is equivalent to
+        * 1000000000 (1sec).
+        */
+       unsigned time_gran;
+
        /**
         * For future use.
         */
-       unsigned reserved[23];
+       unsigned reserved[22];
 };
 
 struct fuse_session;
index 797472139a650aef4cbc7ce1cc3c9c6d4fc3714d..d1b4e2ca9672e85f7e4093536844edc4bb92b269 100644 (file)
@@ -96,6 +96,8 @@
  *
  * 7.23
  *  - add FUSE_WRITEBACK_CACHE
+ *  - add time_gran to fuse_init_out
+ *  - add reserved space to fuse_init_out
  */
 
 #ifndef _LINUX_FUSE_H
 #define FUSE_KERNEL_VERSION 7
 
 /** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 22
+#define FUSE_KERNEL_MINOR_VERSION 23
 
 /** The node ID of the root inode */
 #define FUSE_ROOT_ID 1
@@ -559,6 +561,9 @@ struct fuse_init_in {
        uint32_t        flags;
 };
 
+#define FUSE_COMPAT_INIT_OUT_SIZE 8
+#define FUSE_COMPAT_22_INIT_OUT_SIZE 24
+
 struct fuse_init_out {
        uint32_t        major;
        uint32_t        minor;
@@ -567,6 +572,8 @@ struct fuse_init_out {
        uint16_t        max_background;
        uint16_t        congestion_threshold;
        uint32_t        max_write;
+       uint32_t        time_gran;
+       uint32_t        unused[9];
 };
 
 #define CUSE_INIT_INFO_MAX 4096
index 4284535654491a0c0884789a080fd7d5b063a894..dc27cb534890745f691040e01210a4dec7889a02 100755 (executable)
@@ -1844,6 +1844,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        struct fuse_init_out outarg;
        struct fuse_ll *f = req->f;
        size_t bufsize = f->bufsize;
+       size_t outargsize = sizeof(outarg);
 
        (void) nodeid;
        if (f->debug) {
@@ -2017,6 +2018,8 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
                outarg.max_background = f->conn.max_background;
                outarg.congestion_threshold = f->conn.congestion_threshold;
        }
+       if (f->conn.proto_minor >= 23)
+               outarg.time_gran = f->conn.time_gran;
 
        if (f->debug) {
                fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
@@ -2028,9 +2031,15 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
                        outarg.max_background);
                fprintf(stderr, "   congestion_threshold=%i\n",
                        outarg.congestion_threshold);
+               fprintf(stderr, "   time_gran=%u\n",
+                       outarg.time_gran);
        }
+       if (arg->minor < 5)
+               outargsize = FUSE_COMPAT_INIT_OUT_SIZE;
+       else if (arg->minor < 23)
+               outargsize = FUSE_COMPAT_22_INIT_OUT_SIZE;
 
-       send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
+       send_reply_ok(req, &outarg, outargsize);
 }
 
 static void do_destroy(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
@@ -2625,6 +2634,7 @@ static const struct fuse_opt fuse_ll_opts[] = {
        { "no_async_dio", offsetof(struct fuse_ll, no_async_dio), 1},
        { "writeback_cache", offsetof(struct fuse_ll, writeback_cache), 1},
        { "no_writeback_cache", offsetof(struct fuse_ll, no_writeback_cache), 1},
+       { "time_gran=%u", offsetof(struct fuse_ll, conn.time_gran), 0 },
        FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
        FUSE_OPT_KEY("-h", KEY_HELP),
        FUSE_OPT_KEY("--help", KEY_HELP),
@@ -2660,6 +2670,7 @@ static void fuse_ll_help(void)
 "    -o readdirplus=S         control readdirplus use (yes|no|auto)\n"
 "    -o [no_]async_dio        asynchronous direct I/O\n"
 "    -o [no_]writeback_cache  asynchronous, buffered writes\n"
+"    -o time_gran=N           time granularity in nsec\n"
 );
 }