aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Nikolaus Rath <Nikolaus@rath.org>2016-10-27 21:38:42 -0700
committerGravatar Nikolaus Rath <Nikolaus@rath.org>2016-10-27 21:38:42 -0700
commite885e84f796da2433907e57358bc4916bca30a50 (patch)
tree278350db190c3f8f50933397d368cc9fbbbe74e9
parent4fade0c616a9227e42043ac3332f0fc59a6df327 (diff)
Add max_read to fuse_conn_info
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.
-rw-r--r--ChangeLog.rst6
-rw-r--r--doc/mount.fuse.88
-rw-r--r--include/fuse_common.h14
-rw-r--r--lib/fuse_i.h1
-rw-r--r--lib/fuse_lowlevel.c8
-rw-r--r--lib/mount.c7
-rw-r--r--lib/mount_bsd.c7
7 files changed, 50 insertions, 1 deletions
diff --git a/ChangeLog.rst b/ChangeLog.rst
index 2019325..65df8a5 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -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.
diff --git a/doc/mount.fuse.8 b/doc/mount.fuse.8
index ada4b07..bc4b2fa 100644
--- a/doc/mount.fuse.8
+++ b/doc/mount.fuse.8
@@ -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
diff --git a/include/fuse_common.h b/include/fuse_common.h
index c3636b8..5840956 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -222,6 +222,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
*/
unsigned max_readahead;
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 50962e3..ec29c4e 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -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);
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 45e9d32..8455669 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -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;
diff --git a/lib/mount.c b/lib/mount.c
index 051b424..bb13c30 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -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;
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index 9cf9dfa..8bff2cf 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -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)
{