Add max_read to fuse_conn_info
authorNikolaus Rath <Nikolaus@rath.org>
Fri, 28 Oct 2016 04:38:42 +0000 (21:38 -0700)
committerNikolaus Rath <Nikolaus@rath.org>
Fri, 28 Oct 2016 04:38:42 +0000 (21:38 -0700)
Eventually, this setting should be negotiated in the filesystem's init()
handler (like e.g. max_write). However, this requires corresponding
changes in the FUSE kernel module. In preparation for this (and to allow
a transition period) we already allow (and require) filesystems to set
the value in the init() handler in addition to the mount option.

The end-goal is tracked in issue #91.

ChangeLog.rst
doc/mount.fuse.8
include/fuse_common.h
lib/fuse_i.h
lib/fuse_lowlevel.c
lib/mount.c
lib/mount_bsd.c

index 2019325a0120689a04b3542f70af42c5aea46a3e..65df8a5d81e428c1fd00035c5fde7796c85e2916 100644 (file)
@@ -1,6 +1,12 @@
 Unreleased Changes
 ==================
 
+* Added a `max_read` field to `struct fuse_conn_info`. For the time
+  being, the maximum size of read requests has to be specified both
+  there *and* passed to fuse_session_new() using the ``-o
+  max_read=<n>`` mount option. At some point in the future, specifying
+  the mount option will no longer be necessary.
+
 * Documentation: clarified that the fuse_argv structure that is passed
   to `fuse_new()` and `fuse_lowlevel_new()` must always contain at
   least one element.
index ada4b0768ab798c58e8d6121d883e6e251bfa406..bc4b2faf0c8edb369d895dac22d1e599e45b031e 100644 (file)
@@ -100,11 +100,17 @@ the filesystem owner but set internally by the filesystem.
 \fBmax_read=N\fP
 With this option the maximum size of read operations can be set. The
 default is infinite, but typically the kernel enforces its own limit
-in addition to this one.
+in addition to this one. A value of zero corresponds to no limit.
 
 This option should not be specified by the filesystem owner. The
 correct (or optimum) value depends on the filesystem implementation
 and should thus be set by the filesystem internally.
+
+This mount option is deprecated in favor of direct negotiation over
+the device fd (as done for e.g. the maximum size of write
+operations). For the time being, libfuse-using filesystems that want
+to limit the read size must therefore use this mount option \fIand\fP
+set the same value again in the init() handler.
 .TP
 \fBfd=N\fP
 The file descriptor to use for communication between the userspace
index c3636b8d2faf7619db7ac977f81157a6a8091851..5840956f0fa18d3764801b6c347e4c4cb38e15f0 100644 (file)
@@ -221,6 +221,20 @@ struct fuse_conn_info {
         */
        unsigned max_write;
 
+       /**
+        * Maximum size of read requests. A value of zero indicates no
+        * limit. However, even if the filesystem does not specify a
+        * limit, the maximum size of read requests will still be
+        * limited by the kernel.
+        *
+        * NOTE: For the time being, the maximum size of read requests
+        * must be set both here *and* passed to fuse_session_new()
+        * using the ``-o max_read=<n>`` mount option. At some point
+        * in the future, specifying the mount option will no longer
+        * be necessary.
+        */
+       unsigned max_read;
+
        /**
         * Maximum readahead
         */
index 50962e323ed2a50a14d2653d13749672175832c3..ec29c4e482489a6aac21c9a3b7f4b6058a20aac8 100644 (file)
@@ -108,6 +108,7 @@ void fuse_chan_put(struct fuse_chan *ch);
 struct mount_opts *parse_mount_opts(struct fuse_args *args);
 void destroy_mount_opts(struct mount_opts *mo);
 void fuse_mount_version(void);
+unsigned get_max_read(struct mount_opts *o);
 void fuse_kern_unmount(const char *mountpoint, int fd);
 int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo);
 
index 45e9d32debdbd9c80f3a3b57efdb5a77d2593635..8455669c6a0344f18a377df1affe31a419c8aef9 100644 (file)
@@ -1916,6 +1916,14 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
        if (se->op.init)
                se->op.init(se->userdata, &se->conn);
 
+       unsigned max_read_mo = get_max_read(se->mo);
+       if (se->conn.max_read != max_read_mo) {
+               fprintf(stderr, "fuse: error: init() and fuse_session_new() "
+                       "requested different maximum read size (%u vs %u)\n",
+                       se->conn.max_read, max_read_mo);
+               abort();
+       }
+
        /* Always enable big writes, this is superseded
           by the max_write option */
        outarg.flags |= FUSE_BIG_WRITES;
index 051b424fcf6d0b47a9f0fbc301c6710a55ac004d..bb13c302c19ae2117cfb4f29b705ebfa036340ee 100644 (file)
@@ -73,6 +73,7 @@ struct mount_opts {
        char *mtab_opts;
        char *fusermount_opts;
        char *kernel_opts;
+       unsigned max_read;
 };
 
 #define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
@@ -83,6 +84,7 @@ static const struct fuse_opt fuse_mount_opts[] = {
        FUSE_MOUNT_OPT("blkdev",                blkdev),
        FUSE_MOUNT_OPT("auto_unmount",          auto_unmount),
        FUSE_MOUNT_OPT("fsname=%s",             fsname),
+       FUSE_MOUNT_OPT("max_read=%u",           max_read),
        FUSE_MOUNT_OPT("subtype=%s",            subtype),
        FUSE_OPT_KEY("allow_other",             KEY_KERN_OPT),
        FUSE_OPT_KEY("allow_root",              KEY_ALLOW_ROOT),
@@ -157,6 +159,11 @@ static const struct mount_flags mount_flags[] = {
        {NULL,      0,              0}
 };
 
+unsigned get_max_read(struct mount_opts *o)
+{
+       return o->max_read;
+}
+
 static void set_mount_flag(const char *s, int *flags)
 {
        int i;
index 9cf9dfad75fd3039fbd248a1b8a7f8f2540ac198..8bff2cf717c0583f165496d4952b9cee798bcdc9 100644 (file)
@@ -40,6 +40,7 @@ struct mount_opts {
        int allow_other;
        int allow_root;
        char *kernel_opts;
+       unsigned max_read;
 };
 
 #define FUSE_DUAL_OPT_KEY(templ, key)                          \
@@ -48,6 +49,7 @@ struct mount_opts {
 static const struct fuse_opt fuse_mount_opts[] = {
        { "allow_other", offsetof(struct mount_opts, allow_other), 1 },
        { "allow_root", offsetof(struct mount_opts, allow_root), 1 },
+       { "max_read=%u", offsetof(struct mount_opts, max_read), 1 },
        FUSE_OPT_KEY("allow_root",              KEY_ALLOW_ROOT),
        FUSE_OPT_KEY("-r",                      KEY_RO),
        /* standard FreeBSD mount options */
@@ -98,6 +100,11 @@ void fuse_mount_version(void)
        system(FUSERMOUNT_PROG " --version");
 }
 
+unsigned get_max_read(struct mount_opts *o)
+{
+       return o->max_read;
+}
+
 static int fuse_mount_opt_proc(void *data, const char *arg, int key,
                               struct fuse_args *outargs)
 {