added lowlevel API
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 495eb1d..b89ad93 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -6,7 +6,8 @@
     See the file COPYING.LIB
 */
 
-#include "fuse_lowlevel.h"
+#include <config.h>
+#include "fuse_lowlevel_i.h"
 #include "fuse_kernel.h"
 
 #include <stdio.h>
@@ -22,19 +23,6 @@
 
 #define PARAM(inarg) (((char *)(inarg)) + sizeof(*(inarg)))
 
-struct fuse_ll {
-    unsigned int debug : 1;
-    unsigned int allow_root : 1;
-    int fd;
-    struct fuse_ll_operations op;
-    volatile int exited;
-    int got_init;
-    void *user_data;
-    int major;
-    int minor;
-    uid_t owner;
-};
-
 struct fuse_cmd {
     char *buf;
     size_t buflen;
@@ -43,11 +31,22 @@
 struct fuse_req {
     struct fuse_ll *f;
     uint64_t unique;
-    uid_t uid;
-    gid_t gid;
-    pid_t pid;
+    struct fuse_ctx ctx;
 };
 
+#ifndef USE_UCLIBC
+#define mutex_init(mut) pthread_mutex_init(mut, NULL)
+#else
+static void mutex_init(pthread_mutex_t *mut)
+{
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
+    pthread_mutex_init(mut, &attr);
+    pthread_mutexattr_destroy(&attr);
+}
+#endif
+
 static const char *opname(enum fuse_opcode opcode)
 {
     switch (opcode) {
@@ -83,6 +82,20 @@
     }
 }
 
+static inline void fuse_dec_avail(struct fuse_ll *f)
+{
+    pthread_mutex_lock(&f->worker_lock);
+    f->numavail --;
+    pthread_mutex_unlock(&f->worker_lock);
+}
+
+static inline void fuse_inc_avail(struct fuse_ll *f)
+{
+    pthread_mutex_lock(&f->worker_lock);
+    f->numavail ++;
+    pthread_mutex_unlock(&f->worker_lock);
+}
+
 static void convert_stat(const struct stat *stbuf, struct fuse_attr *attr)
 {
     attr->ino       = stbuf->st_ino;
@@ -143,10 +156,15 @@
         fflush(stdout);
     }
 
+    /* This needs to be done before the reply, otherwise the scheduler
+       could play tricks with us, and only let the counter be
+       increased long after the operation is done */
+    fuse_inc_avail(f);
+
     res = writev(f->fd, iov, count);
     if (res == -1) {
         /* ENOENT means the operation was interrupted */
-        if (!f->exited && errno != ENOENT)
+        if (!fuse_ll_exited(f) && errno != ENOENT)
             perror("fuse: writing device");
         return -errno;
     }
@@ -589,10 +607,10 @@
         fuse_reply_err(req, ENOSYS);
 }
 
-static void do_statfs(fuse_req_t req, fuse_ino_t nodeid)
+static void do_statfs(fuse_req_t req)
 {
     if (req->f->op.statfs)
-        req->f->op.statfs(req, nodeid);
+        req->f->op.statfs(req);
     else
         fuse_reply_err(req, ENOSYS);
 }
@@ -647,7 +665,7 @@
     }
     f->got_init = 1;
     if (f->op.init)
-        f->user_data = f->op.init();
+        f->userdata = f->op.init(f->userdata);
 
     f->major = FUSE_KERNEL_VERSION;
     f->minor = FUSE_KERNEL_MINOR_VERSION;
@@ -664,6 +682,16 @@
     send_reply(f, unique, 0, &outarg, sizeof(outarg));
 }
 
+void *fuse_req_userdata(fuse_req_t req)
+{
+    return req->f->userdata;
+}
+
+const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
+{
+    return &req->ctx;
+}
+
 static void free_cmd(struct fuse_cmd *cmd)
 {
     free(cmd->buf);
@@ -676,6 +704,8 @@
     void *inarg = cmd->buf + sizeof(struct fuse_in_header);
     struct fuse_req *req;
 
+    fuse_dec_avail(f);
+
     if (f->debug) {
         printf("unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %i\n",
                in->unique, opname(in->opcode), in->opcode,
@@ -708,9 +738,9 @@
     
     req->f = f;
     req->unique = in->unique;
-    req->uid = in->uid;
-    req->gid = in->gid;
-    req->pid = in->pid;
+    req->ctx.uid = in->uid;
+    req->ctx.gid = in->gid;
+    req->ctx.pid = in->pid;
 
     switch (in->opcode) {
     case FUSE_LOOKUP:
@@ -783,7 +813,7 @@
         break;
 
     case FUSE_STATFS:
-        do_statfs(req, in->nodeid);
+        do_statfs(req);
         break;
 
     case FUSE_FSYNC:
@@ -830,6 +860,11 @@
     free_cmd(cmd);
 }
 
+void fuse_ll_exit(struct fuse_ll *f)
+{
+    f->exited = 1;
+}
+
 int fuse_ll_exited(struct fuse_ll* f)
 {
     return f->exited;
@@ -868,14 +903,14 @@
             perror("fuse: reading device");
         }
 
-        f->exited = 1;
+        fuse_ll_exit(f);
         return NULL;
     }
     if ((size_t) res < sizeof(struct fuse_in_header)) {
         free_cmd(cmd);
         /* Cannot happen */
         fprintf(stderr, "short read on fuse device\n");
-        f->exited = 1;
+        fuse_ll_exit(f);
         return NULL;
     }
     cmd->buflen = res;
@@ -941,7 +976,7 @@
 
 struct fuse_ll *fuse_ll_new(int fd, const char *opts,
                             const struct fuse_ll_operations *op,
-                            size_t op_size)
+                            size_t op_size, void *userdata)
 {
     struct fuse_ll *f;
 
@@ -963,6 +998,8 @@
     memcpy(&f->op, op, op_size);
     f->exited = 0;
     f->owner = getuid();
+    f->userdata = userdata;
+    mutex_init(&f->worker_lock);
 
     return f;
 
@@ -974,6 +1011,10 @@
 
 void fuse_ll_destroy(struct fuse_ll *f)
 {
+    if (f->op.destroy)
+        f->op.destroy(f->userdata);
+
+    pthread_mutex_destroy(&f->worker_lock);
     free(f);
 }