aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2005-09-09 13:10:36 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 14:03:47 -0700
commit04730fef1f9c7277e5c730b193e681ac095b0507 (patch)
tree3694ea435eb38f10dadc5c8b6abd603a7e10f52e /fs/fuse/file.c
parent413ef8cb302511d8e995e2b0e5517ee1a65b9c77 (diff)
downloadkernel_goldelico_gta04-04730fef1f9c7277e5c730b193e681ac095b0507.zip
kernel_goldelico_gta04-04730fef1f9c7277e5c730b193e681ac095b0507.tar.gz
kernel_goldelico_gta04-04730fef1f9c7277e5c730b193e681ac095b0507.tar.bz2
[PATCH] fuse: transfer readdir data through device
This patch removes a long lasting "hack" in FUSE, which used a separate channel (a file descriptor refering to a disk-file) to transfer directory contents from userspace to the kernel. The patch adds three new operations (OPENDIR, READDIR, RELEASEDIR), which have semantics and implementation exactly maching the respective file operations (OPEN, READ, RELEASE). This simplifies the directory reading code. Also disk space is not necessary, which can be important in embedded systems. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r--fs/fuse/file.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6bc3fb2..2244535 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -12,7 +12,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
-static int fuse_open(struct inode *inode, struct file *file)
+int fuse_open_common(struct inode *inode, struct file *file, int isdir)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_req *req;
@@ -56,7 +56,7 @@ static int fuse_open(struct inode *inode, struct file *file)
memset(&inarg, 0, sizeof(inarg));
inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
- req->in.h.opcode = FUSE_OPEN;
+ req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->in.numargs = 1;
@@ -85,7 +85,7 @@ static int fuse_open(struct inode *inode, struct file *file)
return err;
}
-static int fuse_release(struct inode *inode, struct file *file)
+int fuse_release_common(struct inode *inode, struct file *file, int isdir)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
@@ -94,7 +94,7 @@ static int fuse_release(struct inode *inode, struct file *file)
inarg->fh = ff->fh;
inarg->flags = file->f_flags & ~O_EXCL;
- req->in.h.opcode = FUSE_RELEASE;
+ req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->in.numargs = 1;
@@ -107,6 +107,16 @@ static int fuse_release(struct inode *inode, struct file *file)
return 0;
}
+static int fuse_open(struct inode *inode, struct file *file)
+{
+ return fuse_open_common(inode, file, 0);
+}
+
+static int fuse_release(struct inode *inode, struct file *file)
+{
+ return fuse_release_common(inode, file, 0);
+}
+
static int fuse_flush(struct file *file)
{
struct inode *inode = file->f_dentry->d_inode;
@@ -178,8 +188,9 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
return err;
}
-static ssize_t fuse_send_read(struct fuse_req *req, struct file *file,
- struct inode *inode, loff_t pos, size_t count)
+size_t fuse_send_read_common(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count,
+ int isdir)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
@@ -189,7 +200,7 @@ static ssize_t fuse_send_read(struct fuse_req *req, struct file *file,
inarg.fh = ff->fh;
inarg.offset = pos;
inarg.size = count;
- req->in.h.opcode = FUSE_READ;
+ req->in.h.opcode = isdir ? FUSE_READDIR : FUSE_READ;
req->in.h.nodeid = get_node_id(inode);
req->inode = inode;
req->file = file;
@@ -204,6 +215,13 @@ static ssize_t fuse_send_read(struct fuse_req *req, struct file *file,
return req->out.args[0].size;
}
+static inline size_t fuse_send_read(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos,
+ size_t count)
+{
+ return fuse_send_read_common(req, file, inode, pos, count, 0);
+}
+
static int fuse_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
@@ -293,8 +311,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
return err;
}
-static ssize_t fuse_send_write(struct fuse_req *req, struct file *file,
- struct inode *inode, loff_t pos, size_t count)
+static size_t fuse_send_write(struct fuse_req *req, struct file *file,
+ struct inode *inode, loff_t pos, size_t count)
{
struct fuse_conn *fc = get_fuse_conn(inode);
struct fuse_file *ff = file->private_data;
@@ -332,7 +350,7 @@ static int fuse_commit_write(struct file *file, struct page *page,
unsigned offset, unsigned to)
{
int err;
- ssize_t nres;
+ size_t nres;
unsigned count = to - offset;
struct inode *inode = page->mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);