fix
diff --git a/kernel/dir.c b/kernel/dir.c
index 076d966..38611c5 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -534,9 +534,9 @@
 	struct page *page;
 	struct inode *inode = file->f_dentry->d_inode;	
 	struct fuse_conn *fc = get_fuse_conn(inode);
-	struct fuse_req *req = fuse_get_request(fc);
+	struct fuse_req *req = fuse_get_request_nonint(fc);
 	if (!req)
-		return -ERESTARTNOINTR;
+		return -EINTR;
 
 	page = alloc_page(GFP_KERNEL);
 	if (!page) {
diff --git a/kernel/file.c b/kernel/file.c
index 41e8d47..0405f7b 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -411,7 +411,7 @@
 #endif /* KERNEL_2_6 */
 
 static size_t fuse_send_write(struct fuse_req *req, struct file *file,
-			       struct inode *inode, loff_t pos, size_t count)
+			      struct inode *inode, loff_t pos, size_t count)
 {
 	struct fuse_conn *fc = get_fuse_conn(inode);
 	struct fuse_file *ff = file->private_data;
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 92fb703..e4d9588 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -321,11 +321,6 @@
 #endif
 };
 
-struct fuse_getdir_out_i {
-	int fd;
-	void *file; /* Used by kernel only */
-};
-
 static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
 {
 #ifdef KERNEL_2_6
@@ -385,6 +380,23 @@
 		      unsigned long nodeid, int version);
 
 /**
+ * Send READ or READDIR request
+ */
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+			     struct inode *inode, loff_t pos, size_t count,
+			     int isdir);
+
+/**
+ * Send OPEN or OPENDIR request
+ */
+int fuse_open_common(struct inode *inode, struct file *file, int isdir);
+
+/**
+ * Send RELEASE or RELEASEDIR request
+ */
+int fuse_release_common(struct inode *inode, struct file *file, int isdir);
+
+/**
  * Initialise file operations on a regular file
  */
 void fuse_init_file_inode(struct inode *inode);
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index 378791b..cd8f46f 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -67,7 +67,6 @@
 	FUSE_SETATTR	   = 4,
 	FUSE_READLINK	   = 5,
 	FUSE_SYMLINK	   = 6,
-	FUSE_GETDIR	   = 7,
 	FUSE_MKNOD	   = 8,
 	FUSE_MKDIR	   = 9,
 	FUSE_UNLINK	   = 10,
@@ -85,7 +84,10 @@
 	FUSE_LISTXATTR     = 23,
 	FUSE_REMOVEXATTR   = 24,
 	FUSE_FLUSH         = 25,
-	FUSE_INIT          = 26
+	FUSE_INIT          = 26,
+	FUSE_OPENDIR       = 27,
+	FUSE_READDIR       = 28,
+	FUSE_RELEASEDIR    = 29
 };
 
 /* Conservative buffer size for the client */
@@ -117,10 +119,6 @@
 	struct fuse_attr attr;
 };
 
-struct fuse_getdir_out {
-	__u32	fd;
-};
-
 struct fuse_mknod_in {
 	__u32	mode;
 	__u32	rdev;
diff --git a/lib/fuse.c b/lib/fuse.c
index 25b62a0..8154feb 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -60,8 +60,8 @@
 
 struct fuse_dirhandle {
     struct fuse *fuse;
-    nodeid_t dir;
     FILE *fp;
+    int filled;
 };
 
 struct fuse_cmd {
@@ -72,6 +72,13 @@
 
 static struct fuse_context *(*fuse_getcontext)(void) = NULL;
 
+/* Compatibility with kernel ABI version 5.1 */
+struct fuse_getdir_out {
+    __u32 fd;
+};
+
+#define FUSE_GETDIR 7 
+
 static const char *opname(enum fuse_opcode opcode)
 {
     switch (opcode) { 
@@ -100,6 +107,9 @@
     case FUSE_LISTXATTR:	return "LISTXATTR";
     case FUSE_REMOVEXATTR:	return "REMOVEXATTR";
     case FUSE_INIT:		return "INIT";
+    case FUSE_OPENDIR:		return "OPENDIR";
+    case FUSE_READDIR:		return "READDIR";
+    case FUSE_RELEASEDIR:	return "RELEASEDIR";
     default: 			return "???";
     }
 }
@@ -805,29 +815,37 @@
     send_reply(f, in, res, link, res == 0 ? strlen(link) : 0);
 }
 
+static int common_getdir(struct fuse *f, struct fuse_in_header *in,
+                       struct fuse_dirhandle *dh)
+{
+    int res;
+    char *path;
+
+    res = -ENOENT;
+    path = get_path(f, in->nodeid);
+    if (path != NULL) {
+        res = -ENOSYS;
+        if (f->op.getdir)
+            res = f->op.getdir(path, dh, fill_dir);
+        free(path);
+    }
+    return res;
+}
+
 static void do_getdir(struct fuse *f, struct fuse_in_header *in)
 {
     int res;
     struct fuse_getdir_out arg;
     struct fuse_dirhandle dh;
-    char *path;
 
     dh.fuse = f;
     dh.fp = tmpfile();
-    dh.dir = in->nodeid;
 
     res = -EIO;
     if (dh.fp == NULL)
         perror("fuse: failed to create temporary file");
     else {
-        res = -ENOENT;
-        path = get_path(f, in->nodeid);
-        if (path != NULL) {
-            res = -ENOSYS;
-            if (f->op.getdir)
-                res = f->op.getdir(path, &dh, fill_dir);
-            free(path);
-        }
+        res = common_getdir(f, in, &dh);
         fflush(dh.fp);
     }
     memset(&arg, 0, sizeof(struct fuse_getdir_out));
@@ -1520,6 +1538,88 @@
     send_reply(f, in, 0, &outarg, sizeof(outarg));
 }
 
+static struct fuse_dirhandle *get_dirhandle(unsigned long fh)
+{
+    return (struct fuse_dirhandle *) fh;
+}
+
+static void do_opendir(struct fuse *f, struct fuse_in_header *in,
+                       struct fuse_open_in *arg)
+{
+    int res;
+    struct fuse_open_out outarg;
+    struct fuse_dirhandle *dh;
+
+    (void) arg;
+
+    res = -ENOMEM;
+    dh = (struct fuse_dirhandle *) malloc(sizeof(struct fuse_dirhandle));
+    if (dh != NULL) {
+        dh->fuse = f;
+        dh->fp = tmpfile();
+        dh->filled = 0;
+        
+        res = -EIO;
+        if (dh->fp == NULL) {
+            perror("fuse: failed to create temporary file");
+            free(dh);
+        } else {
+            outarg.fh = (unsigned long) dh;
+            res = 0;
+        }
+    }
+    send_reply(f, in, res, &outarg, sizeof(outarg));
+}
+
+static void do_readdir(struct fuse *f, struct fuse_in_header *in,
+                       struct fuse_read_in *arg)
+{
+    int res;
+    char *outbuf;
+    struct fuse_dirhandle *dh = get_dirhandle(arg->fh);
+
+    if (!dh->filled) {
+        res = common_getdir(f, in, dh);
+        if (res)
+            send_reply(f, in, res, NULL, 0);
+        dh->filled = 1;
+    }
+    outbuf = (char *) malloc(sizeof(struct fuse_out_header) + arg->size);
+    if (outbuf == NULL)
+        send_reply(f, in, -ENOMEM, NULL, 0);
+    else {
+        struct fuse_out_header *out = (struct fuse_out_header *) outbuf;
+        char *buf = outbuf + sizeof(struct fuse_out_header);
+        size_t size = 0;
+        size_t outsize;
+        fseek(dh->fp, arg->offset, SEEK_SET);
+        res = fread(buf, 1, arg->size, dh->fp);
+        if (res == 0 && ferror(dh->fp))
+            res = -EIO;
+        else {
+            size = res;
+            res = 0;
+        }
+        memset(out, 0, sizeof(struct fuse_out_header));
+        out->unique = in->unique;
+        out->error = res;
+        outsize = sizeof(struct fuse_out_header) + size;
+        
+        send_reply_raw(f, outbuf, outsize);
+        free(outbuf);
+    }
+}
+
+static void do_releasedir(struct fuse *f, struct fuse_in_header *in,
+                          struct fuse_release_in *arg)
+{
+    struct fuse_dirhandle *dh = get_dirhandle(arg->fh);
+    fclose(dh->fp);
+    free(dh);
+    send_reply(f, in, 0, NULL, 0);
+}
+
+
 static void free_cmd(struct fuse_cmd *cmd)
 {
     free(cmd->buf);
@@ -1653,6 +1753,18 @@
         do_init(f, in, (struct fuse_init_in_out *) inarg);
         break;
 
+    case FUSE_OPENDIR:
+        do_opendir(f, in, (struct fuse_open_in *) inarg);
+        break;
+
+    case FUSE_READDIR:
+        do_readdir(f, in, (struct fuse_read_in *) inarg);
+        break;
+
+    case FUSE_RELEASEDIR:
+        do_releasedir(f, in, (struct fuse_release_in *) inarg);
+        break;
+
     default:
         send_reply(f, in, -ENOSYS, NULL, 0);
     }
diff --git a/lib/helper.c b/lib/helper.c
index 2b15628..365b813 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -395,7 +395,7 @@
 #undef fuse_main
 int fuse_main()
 {
-    fprintf(stderr, "This function does not exist\n");
+    fprintf(stderr, "fuse_main(): This function does not exist\n");
     return -1;
 }