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;