fix
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 0bd6c99..13ddab9 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -10,6 +10,7 @@
 #include "fuse_lowlevel.h"
 #include "fuse_kernel.h"
 #include "fuse_opt.h"
+#include "fuse_i.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -27,9 +28,8 @@
     struct fuse_lowlevel_ops op;
     int got_init;
     void *userdata;
-    int major;
-    int minor;
     uid_t owner;
+    struct fuse_conn_info conn;
 };
 
 struct fuse_req {
@@ -263,7 +263,7 @@
 
     /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
        negative entry */
-    if (!e->ino && req->f->minor < 4)
+    if (!e->ino && req->f->conn.proto_minor < 4)
         return fuse_reply_err(req, ENOENT);
 
     memset(&arg, 0, sizeof(arg));
@@ -330,7 +330,7 @@
 int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
 {
     struct fuse_statfs_out arg;
-    size_t size = req->f->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
+    size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
 
     memset(&arg, 0, sizeof(arg));
     convert_statfs(stbuf, &arg.st);
@@ -693,27 +693,51 @@
 
     if (f->debug) {
         printf("INIT: %u.%u\n", arg->major, arg->minor);
+        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+            printf("flags=0x%08x\n", arg->flags);
+            printf("max_readahead=0x%08x\n", arg->max_readahead);
+        }
         fflush(stdout);
     }
-    f->got_init = 1;
-    if (f->op.init)
-        f->op.init(f->userdata);
+    f->conn.proto_major = arg->major;
+    f->conn.proto_minor = arg->minor;
 
-    f->major = FUSE_KERNEL_VERSION;
-    f->minor = arg->minor;
+    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+        if (f->conn.async_read)
+            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
+        if (arg->max_readahead < f->conn.max_readahead)
+            f->conn.max_readahead = arg->max_readahead;
+    } else {
+        f->conn.async_read = 0;
+        f->conn.max_readahead = 0;
+    }
 
     if (bufsize < FUSE_MIN_READ_BUFFER) {
         fprintf(stderr, "fuse: warning: buffer size too small: %i\n", bufsize);
         bufsize = FUSE_MIN_READ_BUFFER;
     }
 
+    bufsize -= 4096;
+    if (bufsize < f->conn.max_write)
+        f->conn.max_write = bufsize;
+
+    f->got_init = 1;
+    if (f->op.init)
+        f->op.init(f->userdata, &f->conn);
+
     memset(&outarg, 0, sizeof(outarg));
-    outarg.major = f->major;
+    outarg.major = FUSE_KERNEL_VERSION;
     outarg.minor = FUSE_KERNEL_MINOR_VERSION;
-    outarg.max_write = bufsize - 4096;
+    if (f->conn.async_read)
+        outarg.flags |= FUSE_ASYNC_READ;
+    outarg.max_readahead = f->conn.max_readahead;
+    outarg.max_write = f->conn.max_write;
 
     if (f->debug) {
         printf("   INIT: %u.%u\n", outarg.major, outarg.minor);
+        printf("   flags=0x%08x\n", outarg.flags);
+        printf("   max_readahead=0x%08x\n", outarg.max_readahead);
+        printf("   max_write=0x%08x\n", outarg.max_write);
         fflush(stdout);
     }
 
@@ -902,6 +926,11 @@
     { "debug", offsetof(struct fuse_ll, debug), 1 },
     { "-d", offsetof(struct fuse_ll, debug), 1 },
     { "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
+    { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
+    { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
+    { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
+    { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
+    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
     FUSE_OPT_KEY("-h", KEY_HELP),
     FUSE_OPT_KEY("--help", KEY_HELP),
     FUSE_OPT_KEY("-V", KEY_VERSION),
@@ -915,6 +944,15 @@
             FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
 }
 
+static void fuse_ll_help(void)
+{
+    fprintf(stderr,
+"    -o max_write=N         set maximum size of write requests\n"
+"    -o max_readahead=N     set maximum readahead\n"
+"    -o async_read          perform reads asynchronously (default)\n"
+"    -o sync_read           perform reads synchronously\n");
+}
+
 static int fuse_ll_opt_proc(void *data, const char *arg, int key,
                             struct fuse_args *outargs)
 {
@@ -922,6 +960,7 @@
 
     switch (key) {
     case KEY_HELP:
+        fuse_ll_help();
         break;
 
     case KEY_VERSION:
@@ -972,6 +1011,10 @@
         goto out;
     }
 
+    f->conn.async_read = 1;
+    f->conn.max_write = UINT_MAX;
+    f->conn.max_readahead = UINT_MAX;
+
     if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
         goto out_free;
 
@@ -991,10 +1034,10 @@
     return NULL;
 }
 
-#ifndef __FreeBSD__
-
 #include "fuse_lowlevel_compat.h"
 
+#ifndef __FreeBSD__
+
 static void fill_open_compat(struct fuse_open_out *arg,
                       const struct fuse_file_info_compat *f)
 {
@@ -1062,3 +1105,49 @@
 __asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
 
 #endif /* __FreeBSD__ */
+
+struct fuse_ll_compat_conf {
+    unsigned max_read;
+    int set_max_read;
+};
+
+static const struct fuse_opt fuse_ll_opts_compat[] = {
+    { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
+    { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
+    FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
+    FUSE_OPT_END
+};
+
+int fuse_sync_compat_args(struct fuse_args *args)
+{
+    struct fuse_ll_compat_conf conf;
+
+    if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
+        return -1;
+
+    if (fuse_opt_insert_arg(args, 1, "-osync_read"))
+        return -1;
+
+    if (conf.set_max_read) {
+        char tmpbuf[64];
+
+        sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
+        if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
+            return -1;
+    }
+    return 0;
+}
+
+struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
+                        const struct fuse_lowlevel_ops_compat25 *op,
+                        size_t op_size, void *userdata)
+{
+    if (fuse_sync_compat_args(args) == -1)
+        return NULL;
+
+    return fuse_lowlevel_new(args, (const struct fuse_lowlevel_ops *) op,
+                             op_size, userdata);
+}
+
+
+__asm__(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");