fix
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 18 Jan 2005 21:19:58 +0000 (21:19 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 18 Jan 2005 21:19:58 +0000 (21:19 +0000)
ChangeLog
kernel/dev.c
kernel/dir.c
kernel/file.c

index 2adb0c6b8d92341c5c5eb8d83518a81433c431d2..e6b147d0052645b98b18ec8b16968e0375ed9efc 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2005-01-18  Miklos Szeredi <miklos@szeredi.hu>
+
+       * KERNEL ABI: remove GETDIR operation, and add OPENDIR, READDIR
+       and RELEASEDIR.  This ends the ugly hack of passing a file
+       descriptor to the kernel, and actually makes the code simpler.
+
 2005-01-17  Miklos Szeredi <miklos@szeredi.hu>
 
        * Released 2.2-pre4
index 3cfe1e7f11a91660e4045c513f62f327e2e95c18..331659e84eaeb75b8ca512d055e54b4d08ead96d 100644 (file)
@@ -661,13 +661,6 @@ static struct fuse_req *request_find(struct fuse_conn *fc, unsigned unique)
        return NULL;
 }
 
-/* fget() needs to be done in this context */
-static void process_getdir(struct fuse_req *req)
-{
-       struct fuse_getdir_out_i *arg = req->out.args[0].value;
-       arg->file = fget(arg->fd);
-}
-
 static int copy_out_args(struct fuse_copy_state *cs, struct fuse_out *out,
                         unsigned nbytes)
 {
@@ -740,8 +733,6 @@ static ssize_t fuse_dev_writev(struct file *file, const struct iovec *iov,
        if (!err) {
                if (req->interrupted)
                        err = -ENOENT;
-               else if (req->in.h.opcode == FUSE_GETDIR && !oh.error)
-                       process_getdir(req);
        } else if (!req->interrupted)
                req->out.h.error = -EIO;
        request_end(fc, req);
index 91fa22cab73ab7d424206d3ca27c4b0f5eec2059..076d9662b4b311aa7ee550d8e4a41ca2b3955ca9 100644 (file)
@@ -520,70 +520,40 @@ static int parse_dirfile(char *buf, size_t nbytes, struct file *file,
        return 0;
 }
 
-static int fuse_checkdir(struct file *cfile, struct file *file)
+static inline size_t fuse_send_readdir(struct fuse_req *req, struct file *file,
+                                      struct inode *inode, loff_t pos,
+                                      size_t count)
 {
-       struct inode *inode;
-       if (!cfile)
-               return -EIO;
-       inode = cfile->f_dentry->d_inode;
-       if (!S_ISREG(inode->i_mode)) {
-               fput(cfile);
-               return -EIO;
-       }
-
-       file->private_data = cfile;
-       return 0;
+       return fuse_send_read_common(req, file, inode, pos, count, 1);
 }
 
-static int fuse_getdir(struct file *file)
+static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       int err;
+       size_t nbytes;
+       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_getdir_out_i outarg;
-       int err;
-
        if (!req)
                return -ERESTARTNOINTR;
 
-       req->in.h.opcode = FUSE_GETDIR;
-       req->in.h.nodeid = get_node_id(inode);
-       req->inode = inode;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(struct fuse_getdir_out);
-       req->out.args[0].value = &outarg;
-       request_send(fc, req);
+       page = alloc_page(GFP_KERNEL);
+       if (!page) {
+               fuse_put_request(fc, req);
+               return -ENOMEM;
+       }
+       req->num_pages = 1;
+       req->pages[0] = page;
+       nbytes = fuse_send_readdir(req, file, inode, file->f_pos, PAGE_SIZE);
        err = req->out.h.error;
        fuse_put_request(fc, req);
        if (!err)
-               err = fuse_checkdir(outarg.file, file);
-       return err;
-}
-
-static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
-{
-       struct file *cfile = file->private_data;
-       char *buf;
-       int ret;
-
-       if (!cfile) {
-               ret = fuse_getdir(file);
-               if (ret)
-                       return ret;
-
-               cfile = file->private_data;
-       }
+               err = parse_dirfile(page_address(page), nbytes, file, dstbuf,
+                                   filldir);
 
-       buf = (char *) __get_free_page(GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       ret = kernel_read(cfile, file->f_pos, buf, PAGE_SIZE);
-       if (ret > 0)
-               ret = parse_dirfile(buf, ret, file, dstbuf, filldir);
-
-       free_page((unsigned long) buf);
-       return ret;
+       __free_page(page);
+       return err;
 }
 
 static char *read_link(struct dentry *dentry)
@@ -663,18 +633,12 @@ static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
 
 static int fuse_dir_open(struct inode *inode, struct file *file)
 {
-       file->private_data = NULL;
-       return 0;
+       return fuse_open_common(inode, file, 1);
 }
 
 static int fuse_dir_release(struct inode *inode, struct file *file)
 {
-       struct file *cfile = file->private_data;
-
-       if (cfile)
-               fput(cfile);
-
-       return 0;
+       return fuse_release_common(inode, file, 1);
 }
 
 static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
index 65efaad05381c1f7e66fe98ad36a3c7e4a47b522..41e8d4754629a2497a653240cdfec676e21a304f 100644 (file)
@@ -16,7 +16,7 @@
 #define PageUptodate(page) Page_Uptodate(page)
 #define clear_page_dirty(page) ClearPageDirty(page)
 #endif
-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;
@@ -54,7 +54,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;
@@ -84,7 +84,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;
@@ -93,7 +93,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;
@@ -106,6 +106,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;
@@ -177,8 +187,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;
@@ -188,7 +199,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;
@@ -203,6 +214,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;
@@ -392,7 +410,7 @@ static int fuse_file_bigread(struct file *file, struct inode *inode,
 }
 #endif /* KERNEL_2_6 */
 
-static ssize_t fuse_send_write(struct fuse_req *req, struct file *file,
+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);
@@ -431,7 +449,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);