caching patch by Michael Grigoriev
diff --git a/ChangeLog b/ChangeLog
index 792395d..a55b11e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2003-09-08  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+	* Integrated caching patch by Michael Grigoriev
+
+2003-09-08  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+	* Added "Filesystems" file with descriptions of projects using
+	FUSE
+
 2003-06-02  Miklos Szeredi <mszeredi@inf.bme.hu>
 
 	* And another spec-file fix by Achim Settelmeier
diff --git a/Filesystems b/Filesystems
new file mode 100644
index 0000000..3d51d3b
--- /dev/null
+++ b/Filesystems
@@ -0,0 +1,25 @@
+Name: OW
+
+Author: Paul H. Alfille <palfille at partners org>
+
+Homepage: http://home.earthlink.net/~palfille/ow.html
+
+Description:
+
+  OWFS is a method under linux to allow 1-wire devices to appear like
+  files in a directory. 
+
+==============================================================================
+Name: FunFS
+
+Author: Michael Grigoriev (Net Integration Technologies) <mag at
+luminal org>
+
+Homepage: http://open.nit.ca/wiki/?page=FunFS
+
+Description:
+
+  FunFS is an advanced network file system with a simple goal: to be
+  better than NFS.
+
+==============================================================================
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index eef77d9..507d872 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -46,6 +46,10 @@
     doing the mount will be allowed to access the filesystem */
 #define FUSE_ALLOW_OTHER         (1 << 1)
 
+/** If the FUSE_KERNEL_CACHE flag is given, then files will be cached
+    until the INVALIDATE operation is invoked */
+#define FUSE_KERNEL_CACHE        (1 << 2)
+
 struct fuse_attr {
 	unsigned int        mode;
 	unsigned int        nlink;
@@ -77,7 +81,7 @@
 
 enum fuse_opcode {
 	FUSE_LOOKUP	= 1,
-	FUSE_FORGET	= 2,
+	FUSE_FORGET	= 2,  /* no reply */
 	FUSE_GETATTR	= 3,
 	FUSE_SETATTR	= 4,
 	FUSE_READLINK	= 5,
@@ -93,7 +97,8 @@
 	FUSE_READ	= 15,
 	FUSE_WRITE	= 16,
 	FUSE_STATFS	= 17,
-	FUSE_RELEASE    = 18
+	FUSE_RELEASE    = 18, /* no reply */
+	FUSE_INVALIDATE = 19  /* user initiated */
 };
 
 /* Conservative buffer size for the client */
@@ -179,6 +184,12 @@
 	int error;
 };
 
+struct fuse_user_header {
+	int unique; /* zero */
+	enum fuse_opcode opcode;
+	unsigned long ino;
+};
+
 struct fuse_dirent {
 	unsigned long ino;
 	unsigned short namelen;
diff --git a/kernel/dev.c b/kernel/dev.c
index e703b11..cdc4b6c 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -359,14 +359,46 @@
 	if(copy_from_user(oh, buf, sizeof(struct fuse_out_header)))
 		return -EFAULT;
 
-        if (oh->error <= -512 || oh->error > 0) {
-                printk("fuse_dev_write: bad error value\n");
-                return -EIO;
-        }
-
 	return 0;
 }
 
+static int fuse_invalidate(struct fuse_conn *fc, struct fuse_user_header *uh)
+{
+	struct inode *inode = iget(fc->sb, uh->ino);
+	if (!inode)
+		return -ENOENT;
+
+	invalidate_inode_pages(inode);
+	iput(inode);
+	return 0;
+}
+
+static int fuse_user_request(struct fuse_conn *fc, const char *buf,
+			     size_t nbytes)
+{
+	struct fuse_user_header uh;
+	int err;
+
+	if (nbytes < sizeof(struct fuse_user_header)) {
+		printk("fuse_dev_write: write is short\n");
+		return -EIO;
+	}
+
+	if(copy_from_user(&uh, buf, sizeof(struct fuse_out_header)))
+		return -EFAULT;
+	
+	switch(uh.opcode) {
+	case FUSE_INVALIDATE:
+		err = fuse_invalidate(fc, &uh);
+		break;
+
+	default:
+		err = -ENOSYS;
+	}
+	return err;
+}
+    
+
 static ssize_t fuse_dev_write(struct file *file, const char *buf,
 			      size_t nbytes, loff_t *off)
 {
@@ -381,7 +413,17 @@
 	err = copy_out_header(&oh, buf, nbytes);
 	if(err)
 		return err;
-	
+
+	if (!oh.unique)	{
+		err = fuse_user_request(fc, buf, nbytes);
+		goto out;
+	}     
+
+        if (oh.error <= -512 || oh.error > 0) {
+                printk("fuse_dev_write: bad error value\n");
+                return -EIO;
+        }
+
 	spin_lock(&fuse_lock);
 	req = request_find(fc, oh.unique);
 	if(req != NULL) {
@@ -408,6 +450,7 @@
 	wake_up(&req->waitq);
 	spin_unlock(&fuse_lock);
 
+  out:
 	if(!err)
 		return nbytes;
 	else
diff --git a/kernel/file.c b/kernel/file.c
index f4688f7..68bf660 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -34,7 +34,7 @@
 	in.args[0].size = sizeof(inarg);
 	in.args[0].value = &inarg;
 	request_send(fc, &in, &out);
-	if(!out.h.error)
+	if(!out.h.error && !(fc->flags & FUSE_KERNEL_CACHE))
 		invalidate_inode_pages(inode);
 
 	return out.h.error;
diff --git a/util/fusermount.c b/util/fusermount.c
index b76c819..754b6a9 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -451,6 +451,7 @@
             " -h    print help\n"
             " -u    unmount\n"
             " -p    check default permissions on files\n"
+            " -c    cache in kernel space if possible\n"
             " -x    allow other users to access the files (only for root)\n",
             progname);
     exit(1);
@@ -479,6 +480,10 @@
             break;
 
         switch(argv[a][1]) {
+        case 'c':
+            flags |= FUSE_KERNEL_CACHE;
+            break;
+
         case 'h':
             usage();
             break;