cleanup
authorMiklos Szeredi <miklos@szeredi.hu>
Wed, 1 Dec 2004 18:39:12 +0000 (18:39 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Wed, 1 Dec 2004 18:39:12 +0000 (18:39 +0000)
ChangeLog
kernel/cleanup.sh
kernel/configure.ac
kernel/dev.c
kernel/dir.c
kernel/file.c
kernel/fuse_i.h
kernel/inode.c

index 441669bf1fd9d6b79802d96186286139e939d2c3..63f8b58ba1446a945227c31a9e9fa877bbab948a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-12-01  Miklos Szeredi <miklos@szeredi.hu>
+
+       * kernel: clean up writing functions
+
+       * kernel: no allocation on write in direct_io mode
+
 2004-11-30  Miklos Szeredi <miklos@szeredi.hu>
 
        * kernel: clean up reading functions
index 6255cb255d647f316380073163d0a6b1d30b86ea..fb0807e0d15101f16a16758e65da7b29e7a2378d 100755 (executable)
@@ -12,5 +12,5 @@ if test "$destdir" = "."; then
 fi
 
 for f in dev.c dir.c file.c inode.c util.c fuse_i.h; do
-    unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -D__user -DMODULE_LICENSE $f > $destdir/$f
+    unifdef -DKERNEL_2_6 -DKERNEL_2_6_6_PLUS -DKERNEL_2_6_10_PLUS -DHAVE_KERNEL_XATTR -DFS_SAFE -DMAX_LFS_FILESIZE -DFUSE_MAINLINE -DBUG_ON -DHAVE_FS_SUBSYS -D__user -DMODULE_LICENSE $f > $destdir/$f
 done
index 3b06f4656d4196fa53c92ba37aa3e37ef34ec008..f078427c2c53d3ba3e7eba5515bd2f22836d5d08 100644 (file)
@@ -49,9 +49,18 @@ if echo "$kernsrcver" | grep -q "^2.4"; then
                [#include <linux/fs.h>])
        CFLAGS="$old_cflags"
 fi
+
+AC_MSG_CHECKING([whether fs_subsys is declared])
+if grep -q fs_subsys $kernelsrc/include/linux/fs.h; then
+       AC_DEFINE(HAVE_FS_SUBSYS, 1, [Kernel defines fs_subsys])
+       AC_MSG_RESULT([yes])
+else
+       AC_MSG_RESULT([no])
+fi
+
 AC_MSG_CHECKING([if kernel has extended attribute support])
 if test -f $kernelsrc/include/linux/xattr.h; then
-       AC_DEFINE(HAVE_KERNEL_XATTR, 1, [Kernel has xattr support],,)
+       AC_DEFINE(HAVE_KERNEL_XATTR, 1, [Kernel has xattr support])
        AC_MSG_RESULT([yes])
 else
        AC_MSG_RESULT([no])
index aca602f5d6d1da21f565914037b7792d6db981de..70a001336bd0760d8092a61bb2a7351c5e361173 100644 (file)
@@ -205,39 +205,74 @@ static void request_wait(struct fuse_conn *fc)
        remove_wait_queue(&fc->waitq, &wait);
 }
 
-static inline int copy_in_one(const void *src, size_t srclen,
-                             char __user **dstp, size_t *dstlenp)
+static inline int copy_in_page(char __user *buf, struct page *page,
+                              unsigned offset, unsigned count)
 {
-       if (*dstlenp < srclen) {
+       char *tmpbuf = kmap(page);
+       int err = copy_to_user(buf, tmpbuf + offset, count);
+       kunmap(page);
+       return err;
+}
+
+static int copy_in_pages(struct fuse_req *req, size_t nbytes, char __user *buf)
+{
+       unsigned i;
+       unsigned offset = req->page_offset;
+       unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+       for (i = 0; i < req->num_pages && nbytes; i++) {
+               struct page *page = req->pages[i];
+               if (page && copy_in_page(buf, page, offset, count))
+                       return -EFAULT;
+               nbytes -= count;
+               buf += count;
+               count = min(nbytes, (unsigned) PAGE_SIZE);
+               offset = 0;
+       }
+       return 0;
+}
+
+static inline int copy_in_one(struct fuse_req *req, size_t argsize,
+                             const void *val, int islast, char __user *buf,
+                             size_t nbytes)
+{
+       if (nbytes < argsize) {
                printk("fuse_dev_read: buffer too small\n");
                return -EINVAL;
        }
-                       
-       if (srclen && copy_to_user(*dstp, src, srclen))
+       if (islast && req->in.argpages) 
+               return copy_in_pages(req, argsize, buf);
+       else if (argsize && copy_to_user(buf, val, argsize))
                return -EFAULT;
-
-       *dstp += srclen;
-       *dstlenp -= srclen;
-
-       return 0;
+       else
+               return 0;
 }
 
-static inline int copy_in_args(struct fuse_in *in, char __user *buf,
-                              size_t nbytes)
+static int copy_in_args(struct fuse_req *req, char __user *buf, size_t nbytes)
 {
-       int err;
        int i;
+       int err;
+       struct fuse_in *in = &req->in;
        size_t orignbytes = nbytes;
-               
-       err = copy_in_one(&in->h, sizeof(in->h), &buf, &nbytes);
+       unsigned argsize;
+       
+       argsize = sizeof(in->h);
+       err = copy_in_one(req, argsize, &in->h, 0, buf, nbytes);
        if (err)
                return err;
 
+       buf += argsize;
+       nbytes -= argsize;
+
        for (i = 0; i < in->numargs; i++) {
                struct fuse_in_arg *arg = &in->args[i];
-               err = copy_in_one(arg->value, arg->size, &buf, &nbytes);
+               int islast = (i == in->numargs - 1);
+               err = copy_in_one(req, arg->size, arg->value, islast, buf, 
+                                 nbytes);
                if (err)
                        return err;
+
+               buf += arg->size;
+               nbytes -= arg->size;
        }
 
        return orignbytes - nbytes;
@@ -269,7 +304,7 @@ static ssize_t fuse_dev_read(struct file *file, char __user *buf,
        if (req == NULL)
                return -EINTR;
 
-       ret = copy_in_args(&req->in, buf, nbytes);
+       ret = copy_in_args(req, buf, nbytes);
        spin_lock(&fuse_lock);
        if (req->isreply) {
                if (ret < 0) {
@@ -312,91 +347,78 @@ static void process_getdir(struct fuse_req *req)
        arg->file = fget(arg->fd);
 }
 
-static int copy_out_pages(struct fuse_req *req, const char __user *buf,
-                         size_t nbytes)
+static inline int copy_out_page(const char __user *buf, struct page *page,
+                               unsigned offset, unsigned count, int zeroing)
+{
+       int err = 0;
+       char *tmpbuf = kmap(page);
+       if (count < PAGE_SIZE && zeroing)
+               memset(tmpbuf, 0, PAGE_SIZE);
+       if (count)
+               err = copy_from_user(tmpbuf + offset, buf, count);
+       flush_dcache_page(page);
+       kunmap(page);
+       return err;
+}
+
+static int copy_out_pages(struct fuse_req *req, size_t nbytes,
+                         const char __user *buf)
 {
-       unsigned count;
-       unsigned page_offset;
-       unsigned zeroing = req->out.page_zeroing;
        unsigned i;
-       
-       req->out.args[0].size = nbytes;
-       page_offset = req->page_offset;
-       count = min(nbytes, (unsigned) PAGE_CACHE_SIZE - page_offset);
+       unsigned offset = req->page_offset;
+       unsigned zeroing = req->out.page_zeroing;
+       unsigned count = min(nbytes, (unsigned) PAGE_SIZE - offset);
+
        for (i = 0; i < req->num_pages && (zeroing || nbytes); i++) {
                struct page *page = req->pages[i];
-               char *tmpbuf = kmap(page);
-               int err = 0;
-               if (count < PAGE_CACHE_SIZE && zeroing)
-                       memset(tmpbuf, 0, PAGE_CACHE_SIZE);
-               if (count)
-                       err = copy_from_user(tmpbuf + page_offset, buf, count);
-               flush_dcache_page(page);
-               kunmap(page);
-               if (err)
-                       return -EFAULT;
+               if (page && copy_out_page(buf, page, offset, count, zeroing))
+                   return -EFAULT;
                nbytes -= count;
                buf += count;
-               count = min(nbytes, (unsigned) PAGE_CACHE_SIZE);
-               page_offset = 0;
+               count = min(nbytes, (unsigned) PAGE_SIZE);
+               offset = 0;
        }
        return 0;
 }
 
-static inline int copy_out_one(struct fuse_out_arg *arg,
-                              const char __user **srcp,
-                              size_t *srclenp, int allowvar)
+static inline int copy_out_one(struct fuse_req *req, struct fuse_out_arg *arg,
+                              int islast, const char __user *buf, size_t nbytes)
 {
-       size_t dstlen = arg->size;
-       if (*srclenp < dstlen) {
-               if (!allowvar) {
+       if (nbytes < arg->size) {
+               if (!islast || !req->out.argvar) {
                        printk("fuse_dev_write: write is short\n");
                        return -EINVAL;
                }
-               dstlen = *srclenp;
+               arg->size = nbytes;
        }
-
-       if (dstlen && copy_from_user(arg->value, *srcp, dstlen))
+       if (islast && req->out.argpages)
+               return copy_out_pages(req, arg->size, buf);
+       else if (arg->size && copy_from_user(arg->value, buf, arg->size))
                return -EFAULT;
-
-       *srcp += dstlen;
-       *srclenp -= dstlen;
-       arg->size = dstlen;
-
-       return 0;
+       else
+               return 0;
 }
 
-static inline int copy_out_args(struct fuse_req *req, const char __user *buf,
-                               size_t nbytes)
+static int copy_out_args(struct fuse_req *req, const char __user *buf,
+                        size_t nbytes)
 {
        struct fuse_out *out = &req->out;
-       int err;
        int i;
 
        buf += sizeof(struct fuse_out_header);
        nbytes -= sizeof(struct fuse_out_header);
                
        if (!out->h.error) {
-               if (out->argpages) {
-                       if (nbytes <= out->args[0].size)
-                               return copy_out_pages(req, buf, nbytes);
-               } else {
-                       for (i = 0; i < out->numargs; i++) {
-                               struct fuse_out_arg *arg = &out->args[i];
-                               int allowvar;
-                               
-                               if (out->argvar && i == out->numargs - 1)
-                                       allowvar = 1;
-                               else
-                                       allowvar = 0;
-                               
-                               err = copy_out_one(arg, &buf, &nbytes, allowvar);
-                               if (err)
-                                       return err;
-                       }
+               for (i = 0; i < out->numargs; i++) {
+                       struct fuse_out_arg *arg = &out->args[i];
+                       int islast = (i == out->numargs - 1);
+                       int err = copy_out_one(req, arg, islast, buf, nbytes);
+                       if (err)
+                               return err;
+                       buf += arg->size;
+                       nbytes -= arg->size;
                }
        }
-
        if (nbytes != 0) {
                printk("fuse_dev_write: write is long\n");
                return -EINVAL;
@@ -412,7 +434,6 @@ static inline int copy_out_header(struct fuse_out_header *oh,
                printk("fuse_dev_write: write is short\n");
                return -EINVAL;
        }
-       
        if (copy_from_user(oh, buf, sizeof(struct fuse_out_header)))
                return -EFAULT;
 
@@ -591,7 +612,7 @@ struct file_operations fuse_dev_operations = {
 };
 
 #ifdef KERNEL_2_6
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
 static decl_subsys(fs, NULL, NULL);
 #endif
 static decl_subsys(fuse, NULL, NULL);
@@ -607,7 +628,7 @@ static int __init fuse_version_init(void)
 {
        int err;
 
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
        subsystem_register(&fs_subsys);
 #endif
        kset_set_kset_s(&fuse_subsys, fs_subsys);
@@ -617,7 +638,7 @@ static int __init fuse_version_init(void)
        err = subsys_create_file(&fuse_subsys, &fuse_attr_version);
        if (err) {
                subsystem_unregister(&fuse_subsys);
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
                subsystem_unregister(&fs_subsys);
 #endif
                return err;
@@ -629,7 +650,7 @@ static void fuse_version_clean(void)
 {
        subsys_remove_file(&fuse_subsys, &fuse_attr_version);
        subsystem_unregister(&fuse_subsys);
-#ifndef FUSE_MAINLINE
+#ifndef HAVE_FS_SUBSYS
        subsystem_unregister(&fs_subsys);
 #endif 
 }
index 412ffc88ddd91d12c746ace6d536efc38af763a9..a56f51393ec4a40ee79143b289440a97ee783e2a 100644 (file)
@@ -92,8 +92,7 @@ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
 static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
 {
        unsigned long nodeid = *(unsigned long *) _nodeidp;
-       struct fuse_inode *fi = INO_FI(inode);
-       if (fi->nodeid == nodeid)
+       if (get_node_id(inode) == nodeid)
                return 1;
        else
                return 0;
@@ -102,8 +101,7 @@ static int fuse_inode_eq(struct inode *inode, void *_nodeidp)
 static int fuse_inode_set(struct inode *inode, void *_nodeidp)
 {
        unsigned long nodeid = *(unsigned long *) _nodeidp;
-       struct fuse_inode *fi = INO_FI(inode);
-       fi->nodeid = nodeid;
+       get_fuse_inode(inode)->nodeid = nodeid;
        return 0;
 }
 
@@ -111,7 +109,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
                        int generation, struct fuse_attr *attr, int version)
 {
        struct inode *inode;
-       struct fuse_conn *fc = SB_FC(sb);
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        inode = iget5_locked(sb, nodeid, fuse_inode_eq, fuse_inode_set, &nodeid);
        if (!inode)
@@ -137,8 +135,7 @@ struct inode *fuse_ilookup(struct super_block *sb, unsigned long nodeid)
 #else
 static int fuse_inode_eq(struct inode *inode, unsigned long ino, void *_nodeidp){
        unsigned long nodeid = *(unsigned long *) _nodeidp;
-       struct fuse_inode *fi = INO_FI(inode);
-       if (inode->u.generic_ip && fi->nodeid == nodeid)
+       if (inode->u.generic_ip && get_node_id(inode) == nodeid)
                return 1;
        else
                return 0;
@@ -154,8 +151,7 @@ struct inode *fuse_iget(struct super_block *sb, unsigned long nodeid,
                return NULL;
 
        if (!inode->u.generic_ip) {
-               struct fuse_inode *fi = INO_FI(inode);
-               fi->nodeid = nodeid;
+               get_fuse_inode(inode)->nodeid = nodeid;
                inode->u.generic_ip = inode;
                inode->i_generation = generation;
                fuse_init_inode(inode, attr);
@@ -182,9 +178,8 @@ static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
                            struct inode *dir, struct dentry *entry, 
                            struct fuse_entry_out *outarg, int *version)
 {
-       struct fuse_inode *fi = INO_FI(dir);
        req->in.h.opcode = FUSE_LOOKUP;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 1;
        req->in.args[0].size = entry->d_name.len + 1;
        req->in.args[0].value = entry->d_name.name;
@@ -199,7 +194,7 @@ static int fuse_send_lookup(struct fuse_conn *fc, struct fuse_req *req,
 static int fuse_do_lookup(struct inode *dir, struct dentry *entry,
                          struct fuse_entry_out *outarg, int *version)
 {
-       struct fuse_conn *fc = INO_FC(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req;
        int err;
 
@@ -227,7 +222,7 @@ static inline unsigned long time_to_jiffies(unsigned long sec,
 static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
                            struct inode **inodep)
 {
-       struct fuse_conn *fc = INO_FC(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        int err;
        struct fuse_entry_out outarg;
        int version;
@@ -254,7 +249,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
                return err;
 
        if (inode) {
-               struct fuse_inode *fi = INO_FI(inode);
+               struct fuse_inode *fi = get_fuse_inode(inode);
                entry->d_time = time_to_jiffies(outarg.entry_valid,
                                                outarg.entry_valid_nsec);
                fi->i_time = time_to_jiffies(outarg.attr_valid,
@@ -268,8 +263,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
 
 static void fuse_invalidate_attr(struct inode *inode)
 {
-       struct fuse_inode *fi = INO_FI(inode);
-       fi->i_time = jiffies - 1;
+       get_fuse_inode(inode)->i_time = jiffies - 1;
 }
 
 static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
@@ -297,7 +291,7 @@ static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
        entry->d_time = time_to_jiffies(outarg->entry_valid,
                                        outarg->entry_valid_nsec);
 
-       fi = INO_FI(inode);
+       fi = get_fuse_inode(inode);
        fi->i_time = time_to_jiffies(outarg->attr_valid,
                                     outarg->attr_valid_nsec);
 
@@ -309,8 +303,7 @@ static int lookup_new_entry(struct fuse_conn *fc, struct fuse_req *req,
 static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
                      dev_t rdev)
 {
-       struct fuse_conn *fc = INO_FC(dir);
-       struct fuse_inode *fi = INO_FI(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req = fuse_get_request(fc);
        struct fuse_mknod_in inarg;
        struct fuse_entry_out outarg;
@@ -323,7 +316,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
        inarg.mode = mode;
        inarg.rdev = new_encode_dev(rdev);
        req->in.h.opcode = FUSE_MKNOD;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 2;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -350,8 +343,7 @@ static int fuse_create(struct inode *dir, struct dentry *entry, int mode,
 
 static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
 {
-       struct fuse_conn *fc = INO_FC(dir);
-       struct fuse_inode *fi = INO_FI(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req = fuse_get_request(fc);
        struct fuse_mkdir_in inarg;
        struct fuse_entry_out outarg;
@@ -363,7 +355,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
        memset(&inarg, 0, sizeof(inarg));
        inarg.mode = mode;
        req->in.h.opcode = FUSE_MKDIR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 2;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -385,8 +377,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, int mode)
 static int fuse_symlink(struct inode *dir, struct dentry *entry,
                        const char *link)
 {
-       struct fuse_conn *fc = INO_FC(dir);
-       struct fuse_inode *fi = INO_FI(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req;
        struct fuse_entry_out outarg;
        unsigned len = strlen(link) + 1;
@@ -400,7 +391,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_SYMLINK;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 2;
        req->in.args[0].size = entry->d_name.len + 1;
        req->in.args[0].value = entry->d_name.name;
@@ -421,8 +412,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
 
 static int fuse_unlink(struct inode *dir, struct dentry *entry)
 {
-       struct fuse_conn *fc = INO_FC(dir);
-       struct fuse_inode *fi = INO_FI(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req = fuse_get_request(fc);
        int err;
        
@@ -430,7 +420,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_UNLINK;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 1;
        req->in.args[0].size = entry->d_name.len + 1;
        req->in.args[0].value = entry->d_name.name;
@@ -452,8 +442,7 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry)
 
 static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 {
-       struct fuse_conn *fc = INO_FC(dir);
-       struct fuse_inode *fi = INO_FI(dir);
+       struct fuse_conn *fc = get_fuse_conn(dir);
        struct fuse_req *req = fuse_get_request(fc);
        int err;
        
@@ -461,7 +450,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_RMDIR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(dir);
        req->in.numargs = 1;
        req->in.args[0].size = entry->d_name.len + 1;
        req->in.args[0].value = entry->d_name.name;
@@ -478,9 +467,7 @@ static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 static int fuse_rename(struct inode *olddir, struct dentry *oldent,
                       struct inode *newdir, struct dentry *newent)
 {
-       struct fuse_conn *fc = INO_FC(olddir);
-       struct fuse_inode *oldfi = INO_FI(olddir);
-       struct fuse_inode *newfi = INO_FI(newdir);
+       struct fuse_conn *fc = get_fuse_conn(olddir);
        struct fuse_req *req = fuse_get_request(fc);
        struct fuse_rename_in inarg;
        int err;
@@ -489,9 +476,9 @@ static int fuse_rename(struct inode *olddir, struct dentry *oldent,
                return -ERESTARTSYS;
 
        memset(&inarg, 0, sizeof(inarg));
-       inarg.newdir = newfi->nodeid;
+       inarg.newdir = get_node_id(newdir);
        req->in.h.opcode = FUSE_RENAME;
-       req->in.h.nodeid = oldfi->nodeid;
+       req->in.h.nodeid = get_node_id(olddir);
        req->in.numargs = 3;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -514,9 +501,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
                     struct dentry *newent)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_inode *newfi = INO_FI(newdir);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req = fuse_get_request(fc);
        struct fuse_link_in inarg;
        struct fuse_entry_out outarg;
@@ -526,9 +511,9 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
                return -ERESTARTSYS;
 
        memset(&inarg, 0, sizeof(inarg));
-       inarg.newdir = newfi->nodeid;
+       inarg.newdir = get_node_id(newdir);
        req->in.h.opcode = FUSE_LINK;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 2;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -551,8 +536,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
 
 int fuse_do_getattr(struct inode *inode)
 {
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req = fuse_get_request(fc);
        struct fuse_attr_out arg;
        int err;
@@ -561,13 +545,14 @@ int fuse_do_getattr(struct inode *inode)
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_GETATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->out.numargs = 1;
        req->out.args[0].size = sizeof(arg);
        req->out.args[0].value = &arg;
        request_send(fc, req);
        err = req->out.h.error; 
        if (!err) {
+               struct fuse_inode *fi = get_fuse_inode(inode);
                change_attributes(inode, &arg.attr);
                fi->i_time = time_to_jiffies(arg.attr_valid,
                                             arg.attr_valid_nsec);
@@ -579,10 +564,10 @@ int fuse_do_getattr(struct inode *inode)
 static int fuse_revalidate(struct dentry *entry)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
 
-       if (fi->nodeid == FUSE_ROOT_ID) {
+       if (get_node_id(inode) == FUSE_ROOT_ID) {
                if (!(fc->flags & FUSE_ALLOW_OTHER) &&
                    current->fsuid != fc->uid &&
                    (!(fc->flags & FUSE_ALLOW_ROOT) ||
@@ -596,7 +581,7 @@ static int fuse_revalidate(struct dentry *entry)
 
 static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
 
        if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->uid &&
            (!(fc->flags & FUSE_ALLOW_ROOT) || current->fsuid != 0))
@@ -692,8 +677,7 @@ static int fuse_checkdir(struct file *cfile, struct file *file)
 static int fuse_getdir(struct file *file)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(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;
@@ -702,7 +686,7 @@ static int fuse_getdir(struct file *file)
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_GETDIR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->out.numargs = 1;
        req->out.args[0].size = sizeof(struct fuse_getdir_out);
        req->out.args[0].value = &outarg;
@@ -745,8 +729,7 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
 static char *read_link(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req = fuse_get_request(fc);
        char *link;
 
@@ -759,7 +742,7 @@ static char *read_link(struct dentry *dentry)
                goto out;
        }
        req->in.h.opcode = FUSE_READLINK;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->out.argvar = 1;
        req->out.numargs = 1;
        req->out.args[0].size = PAGE_SIZE - 1;
@@ -853,8 +836,8 @@ static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr)
 static int fuse_setattr(struct dentry *entry, struct iattr *attr)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_req *req;
        struct fuse_setattr_in inarg;
        struct fuse_attr_out outarg;
@@ -891,7 +874,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
        memset(&inarg, 0, sizeof(inarg));
        inarg.valid = iattr_to_fattr(attr, &inarg.attr);
        req->in.h.opcode = FUSE_SETATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -925,7 +908,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                return 0;
        else if (entry->d_time && time_after(jiffies, entry->d_time)) {
                struct inode *inode = entry->d_inode;
-               struct fuse_inode *fi = INO_FI(inode);
+               struct fuse_inode *fi = get_fuse_inode(inode);
                struct fuse_entry_out outarg;
                int version;
                int ret;
@@ -935,7 +918,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                if (ret)
                        return 0;
                
-               if (outarg.nodeid != fi->nodeid)
+               if (outarg.nodeid != get_node_id(inode))
                        return 0;
                
                change_attributes(inode, &outarg.attr);
@@ -1023,8 +1006,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
 #endif
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_setxattr_in inarg;
        int err;
@@ -1043,7 +1025,7 @@ static int fuse_setxattr(struct dentry *entry, const char *name,
        inarg.size = size;
        inarg.flags = flags;
        req->in.h.opcode = FUSE_SETXATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 3;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -1065,8 +1047,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
                             void *value, size_t size)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
@@ -1082,7 +1063,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        req->in.h.opcode = FUSE_GETXATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 2;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -1115,8 +1096,7 @@ static ssize_t fuse_getxattr(struct dentry *entry, const char *name,
 static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_getxattr_in inarg;
        struct fuse_getxattr_out outarg;
@@ -1132,7 +1112,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
        memset(&inarg, 0, sizeof(inarg));
        inarg.size = size;
        req->in.h.opcode = FUSE_LISTXATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -1163,8 +1143,7 @@ static ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
 static int fuse_removexattr(struct dentry *entry, const char *name)
 {
        struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        int err;
        
@@ -1176,7 +1155,7 @@ static int fuse_removexattr(struct dentry *entry, const char *name)
                return -ERESTARTSYS;
 
        req->in.h.opcode = FUSE_REMOVEXATTR;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = strlen(name) + 1;
        req->in.args[0].value = name;
index 2d15c5bb8344b7bcc32872a88e0839aae56a4605..da0fbb85737666f4a5de5d5a9e62179dc219918a 100644 (file)
@@ -29,8 +29,7 @@ MODULE_PARM_DESC(user_mmap, "Allow non root user to create a shared writable map
 
 static int fuse_open(struct inode *inode, struct file *file)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req;
        struct fuse_open_in inarg;
        struct fuse_open_out outarg;
@@ -43,7 +42,7 @@ static int fuse_open(struct inode *inode, struct file *file)
 
        /* If opening the root node, no lookup has been performed on
           it, so the attributes must be refreshed */
-       if (fi->nodeid == FUSE_ROOT_ID) {
+       if (get_node_id(inode) == FUSE_ROOT_ID) {
                int err = fuse_do_getattr(inode);
                if (err)
                        return err;
@@ -69,7 +68,7 @@ static int fuse_open(struct inode *inode, struct file *file)
        memset(&inarg, 0, sizeof(inarg));
        inarg.flags = file->f_flags & ~O_EXCL;
        req->in.h.opcode = FUSE_OPEN;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -117,8 +116,7 @@ void fuse_sync_inode(struct inode *inode)
 
 static int fuse_release(struct inode *inode, struct file *file)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req = ff->release_req;
        struct fuse_release_in inarg;
@@ -128,6 +126,7 @@ static int fuse_release(struct inode *inode, struct file *file)
                fuse_sync_inode(inode);
 
        if (!list_empty(&ff->ff_list)) {
+               struct fuse_inode *fi = get_fuse_inode(inode);
                down_write(&fi->write_sem);
                list_del(&ff->ff_list);
                up_write(&fi->write_sem);
@@ -137,7 +136,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.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -153,8 +152,7 @@ static int fuse_release(struct inode *inode, struct file *file)
 static int fuse_flush(struct file *file)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req = ff->release_req;
        struct fuse_flush_in inarg;
@@ -167,7 +165,7 @@ static int fuse_flush(struct file *file)
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
        req->in.h.opcode = FUSE_FLUSH;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -185,8 +183,8 @@ static int fuse_flush(struct file *file)
 static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
 {
        struct inode *inode = de->d_inode;
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_req *req;
        struct fuse_fsync_in inarg;
@@ -208,7 +206,7 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
        inarg.fh = ff->fh;
        inarg.datasync = datasync;
        req->in.h.opcode = FUSE_FSYNC;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(inarg);
        req->in.args[0].value = &inarg;
@@ -225,7 +223,6 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync)
 static void fuse_read_init(struct fuse_req *req, struct file *file,
                           struct inode *inode, loff_t pos, size_t count)
 {
-       struct fuse_inode *fi = INO_FI(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_read_in *inarg = &req->misc.read_in;
 
@@ -233,11 +230,13 @@ static void fuse_read_init(struct fuse_req *req, struct file *file,
        inarg->offset = pos;
        inarg->size = count;
        req->in.h.opcode = FUSE_READ;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
        req->in.args[0].size = sizeof(struct fuse_read_in);
        req->in.args[0].value = inarg;
+       req->out.argpages = 1;
        req->out.argvar = 1;
+       req->out.page_zeroing = 1;
        req->out.numargs = 1;
        req->out.args[0].size = count;
 }
@@ -245,14 +244,12 @@ static void fuse_read_init(struct fuse_req *req, struct file *file,
 static int fuse_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_req *req = fuse_get_request_nonint(fc);
-       loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT;
+       loff_t pos = (loff_t) page->index << PAGE_SHIFT;
        int err;
        
-       fuse_read_init(req, file, inode, pos, PAGE_CACHE_SIZE);
-       req->out.argpages = 1;
-       req->out.page_zeroing = 1;
+       fuse_read_init(req, file, inode, pos, PAGE_SIZE);
        req->num_pages = 1;
        req->pages[0] = page;
        request_send(fc, req);
@@ -280,12 +277,10 @@ static void read_pages_end(struct fuse_conn *fc, struct fuse_req *req)
 static void fuse_send_readpages(struct fuse_req *req, struct file *file,
                                struct inode *inode)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT;
-       size_t count = req->num_pages << PAGE_CACHE_SHIFT;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       loff_t pos = (loff_t) req->pages[0]->index << PAGE_SHIFT;
+       size_t count = req->num_pages << PAGE_SHIFT;
        fuse_read_init(req, file, inode, pos, count);
-       req->out.argpages = 1;
-       req->out.page_zeroing = 1;
        request_send_async(fc, req, read_pages_end);
 }
 
@@ -300,13 +295,13 @@ static int fuse_readpages_fill(void *_data, struct page *page)
        struct fuse_readpages_data *data = _data;
        struct fuse_req *req = data->req;
        struct inode *inode = data->inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        
        if (req->num_pages && 
            (req->num_pages == FUSE_MAX_PAGES_PER_REQ ||
-            (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read ||
+            (req->num_pages + 1) * PAGE_SIZE > fc->max_read ||
             req->pages[req->num_pages - 1]->index + 1 != page->index)) {
-               struct fuse_conn *fc = INO_FC(page->mapping->host);
+               struct fuse_conn *fc = get_fuse_conn(page->mapping->host);
                fuse_send_readpages(req, data->file, inode);
                data->req = req = fuse_get_request_nonint(fc);
        }
@@ -319,7 +314,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
                          struct list_head *pages, unsigned nr_pages)
 {
        struct inode *inode = mapping->host;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_readpages_data data;
 
        data.req = fuse_get_request_nonint(fc);
@@ -338,7 +333,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
 #define FUSE_BLOCK_SHIFT 16
 #define FUSE_BLOCK_SIZE (1UL << FUSE_BLOCK_SHIFT)
 #define FUSE_BLOCK_MASK (~(FUSE_BLOCK_SIZE-1))
-#if (1UL << (FUSE_BLOCK_SHIFT - PAGE_CACHE_SHIFT)) > FUSE_MAX_PAGES_PER_REQ
+#if (1UL << (FUSE_BLOCK_SHIFT - PAGE_SHIFT)) > FUSE_MAX_PAGES_PER_REQ
 #error FUSE_BLOCK_SHIFT too large
 #endif
 
@@ -364,7 +359,7 @@ static void fuse_file_read_block(struct fuse_req *req, struct file *file,
                                 struct inode *inode, unsigned start,
                                 unsigned end)
 {
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        loff_t pos;
        size_t count;
        int index;
@@ -375,29 +370,34 @@ static void fuse_file_read_block(struct fuse_req *req, struct file *file,
                struct page *page = grab_cache_page(inode->i_mapping, index);
                if (!page)
                        goto out;
+               if (PageUptodate(page)) {
+                       unlock_page(page);
+                       page_cache_release(page);
+                       page = NULL;
+               } 
                req->pages[req->num_pages++] = page;
        }
-       pos = (loff_t) start << PAGE_CACHE_SHIFT;
-       count = req->num_pages << PAGE_CACHE_SHIFT;
+       pos = (loff_t) start << PAGE_SHIFT;
+       count = req->num_pages << PAGE_SHIFT;
        fuse_read_init(req, file, inode, pos, count);
-       req->out.argpages = 1;
-       req->out.page_zeroing = 1;
        request_send(fc, req);
        err = req->out.h.error;
  out:
        for (i = 0; i < req->num_pages; i++) {
                struct page *page = req->pages[i];
-               if (!err)
-                       SetPageUptodate(page);
-               unlock_page(page);
-               page_cache_release(page);
+               if (page) {
+                       if (!err)
+                               SetPageUptodate(page);
+                       unlock_page(page);
+                       page_cache_release(page);
+               }
        }
 }   
 
 static int fuse_file_bigread(struct file *file, struct inode *inode,
                             loff_t pos, size_t count)
 {
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        unsigned starti;
        unsigned endi;
        unsigned nexti;
@@ -408,15 +408,15 @@ static int fuse_file_bigread(struct file *file, struct inode *inode,
        if (end <= pos)
                return 0;
 
-       starti = (pos & FUSE_BLOCK_MASK) >> PAGE_CACHE_SHIFT;
-       endi = (end + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       starti = (pos & FUSE_BLOCK_MASK) >> PAGE_SHIFT;
+       endi = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
        
        req = fuse_get_request(fc);
        if (!req)
                return -ERESTARTSYS;
        
        for (; starti < endi; starti = nexti) {
-               nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_CACHE_SHIFT);
+               nexti = starti + (FUSE_BLOCK_SIZE >> PAGE_SHIFT);
                nexti = min(nexti, endi);
                if (!fuse_is_block_uptodate(inode, starti, nexti)) {
                        fuse_file_read_block(req, file, inode, starti, nexti);
@@ -428,35 +428,37 @@ static int fuse_file_bigread(struct file *file, struct inode *inode,
 }
 #endif /* KERNEL_2_6 */
 
-static void fuse_release_user_pages(struct fuse_req *req)
+static void fuse_release_user_pages(struct fuse_req *req, int write)
 {
        unsigned i;
 
        for (i = 0; i < req->num_pages; i++) {
-               struct page *page = req->pages[i]; 
+               struct page *page = req->pages[i];
+               if (write) {
 #ifdef KERNEL_2_6
-               set_page_dirty_lock(page);
+                       set_page_dirty_lock(page);
 #else
-               lock_page(page);
-               set_page_dirty(page);
-               unlock_page(page);
+                       lock_page(page);
+                       set_page_dirty(page);
+                       unlock_page(page);
 #endif
+               }
                page_cache_release(page);
        }
 }
 
-static int fuse_get_user_pages(struct fuse_req *req, char __user *buf,
-                              unsigned nbytes)
+static int fuse_get_user_pages(struct fuse_req *req, const char __user *buf,
+                              unsigned nbytes, int write)
 {
        unsigned long user_addr = (unsigned long) buf;
-       unsigned offset = user_addr & ~PAGE_CACHE_MASK;
+       unsigned offset = user_addr & ~PAGE_MASK;
        int npages;
 
-       nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_CACHE_SHIFT);
-       npages = (nbytes + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       nbytes = min(nbytes, (unsigned) FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT);
+       npages = (nbytes + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
        npages = min(npages, FUSE_MAX_PAGES_PER_REQ);
-       npages = get_user_pages(current, current->mm, user_addr, npages, 1, 0,
-                               req->pages, NULL);
+       npages = get_user_pages(current, current->mm, user_addr, npages, write,
+                               0, req->pages, NULL);
        if (npages < 0)
                return npages;
 
@@ -469,7 +471,7 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        loff_t pos = *ppos;
        ssize_t res = 0;
        struct fuse_req *req = fuse_get_request(fc);
@@ -477,20 +479,20 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
                return -ERESTARTSYS;
 
        while (count) {
-               unsigned nbytes = min(count, fc->max_read);
                unsigned nread;
                unsigned ntmp;
-               int err = fuse_get_user_pages(req, buf, nbytes);
+               unsigned nbytes = min(count, fc->max_read);
+               int err = fuse_get_user_pages(req, buf, nbytes, 1);
                if (err) {
                        res = err;
                        break;
                }
-               ntmp = (req->num_pages << PAGE_CACHE_SHIFT) - req->page_offset;
+               ntmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
                nbytes = min(nbytes, ntmp);
                fuse_read_init(req, file, inode, pos, nbytes);
-               req->out.argpages = 1;
+               req->out.page_zeroing = 0; /* set to 1 by default */
                request_send(fc, req);
-               fuse_release_user_pages(req);
+               fuse_release_user_pages(req, 1);
                if (req->out.h.error) {
                        if (!res)
                                res = req->out.h.error;
@@ -503,7 +505,8 @@ static ssize_t fuse_direct_read(struct file *file, char __user *buf,
                buf += nread;
                if (nread != nbytes)
                        break;
-               fuse_reset_request(req);
+               if (count)
+                       fuse_reset_request(req);
        }
        fuse_put_request(fc, req);
        if (res > 0)
@@ -516,7 +519,7 @@ static ssize_t fuse_file_read(struct file *file, char __user *buf,
                              size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        ssize_t res;
 
        if (fc->flags & FUSE_DIRECT_IO)
@@ -536,72 +539,31 @@ static ssize_t fuse_file_read(struct file *file, char __user *buf,
        return res;
 }  
 
-static ssize_t fuse_send_write(struct fuse_req *req, struct fuse_file *ff,
-                              struct inode *inode, const char *buf,
-                              loff_t pos, size_t count)
+static void fuse_write_init(struct fuse_req *req, struct fuse_file *ff,
+                           struct inode *inode, loff_t pos, size_t count,
+                           int iswritepage)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_write_in inarg;
-       struct fuse_write_out outarg;
-       ssize_t res;
-       
-       memset(&inarg, 0, sizeof(inarg));
-       inarg.writepage = 0;
-       inarg.fh = ff->fh;
-       inarg.offset = pos;
-       inarg.size = count;
+       struct fuse_write_in *inarg = &req->misc.write.in;
+
+       inarg->writepage = iswritepage;
+       inarg->fh = ff->fh;
+       inarg->offset = pos;
+       inarg->size = count;
        req->in.h.opcode = FUSE_WRITE;
-       req->in.h.nodeid = fi->nodeid;
+       req->in.h.nodeid = get_node_id(inode);
+       if (iswritepage) {
+               req->in.h.uid = 0;
+               req->in.h.gid = 0;
+               req->in.h.pid = 0;
+       }
+       req->in.argpages = 1;
        req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
+       req->in.args[0].size = sizeof(struct fuse_write_in);
+       req->in.args[0].value = inarg;
        req->in.args[1].size = count;
-       req->in.args[1].value = buf;
        req->out.numargs = 1;
-       req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       request_send(fc, req);
-       res = req->out.h.error;
-       if (!res) {
-               if (outarg.size > count)
-                       return -EPROTO;
-               else
-                       return outarg.size;
-       }
-       else
-               return res;
-}
-
-static int write_buffer(struct inode *inode, struct file *file,
-                       struct page *page, unsigned offset, size_t count)
-{
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_file *ff = file->private_data;
-       char *buffer;
-       ssize_t res;
-       loff_t pos;
-       struct fuse_req *req;
-
-       req = fuse_get_request(fc);
-       if (!req)
-               return -ERESTARTSYS;
-       
-       pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
-       buffer = kmap(page);
-       res = fuse_send_write(req, ff, inode, buffer + offset, pos, count);
-       fuse_put_request(fc, req);
-       if (res >= 0) {
-               if (res < count) {
-                       printk("fuse: short write\n");
-                       res = -EPROTO;
-               } else
-                       res = 0;
-       }
-       kunmap(page);
-       if (res)
-               SetPageError(page);
-       return res;
+       req->out.args[0].size = sizeof(struct fuse_write_out);
+       req->out.args[0].value = &req->misc.write.out;
 }
 
 static int get_write_count(struct inode *inode, struct page *page)
@@ -610,28 +572,32 @@ static int get_write_count(struct inode *inode, struct page *page)
        loff_t size = i_size_read(inode);
        int count;
        
-       end_index = size >> PAGE_CACHE_SHIFT;
+       end_index = size >> PAGE_SHIFT;
        if (page->index < end_index)
-               count = PAGE_CACHE_SIZE;
+               count = PAGE_SIZE;
        else {
-               count = size & (PAGE_CACHE_SIZE - 1);
+               count = size & (PAGE_SIZE - 1);
                if (page->index > end_index || count == 0)
                        return 0;
        }
        return count;
 }
 
+static inline struct fuse_file *get_write_file(struct fuse_inode *fi)
+{
+       BUG_ON(list_empty(&fi->write_files));
+       return list_entry(fi->write_files.next, struct fuse_file, ff_list);
+}
+
 #ifdef KERNEL_2_6
 static void write_page_end(struct fuse_conn *fc, struct fuse_req *req)
 {
        struct page *page = req->pages[0];
        struct inode *inode = page->mapping->host;
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_write_out *outarg = req->out.args[0].value;
-       if (!req->out.h.error && outarg->size != req->in.args[1].size) {
-               printk("fuse: short write\n");
+       if (!req->out.h.error && outarg->size != req->in.args[1].size)
                req->out.h.error = -EPROTO;
-       }
 
        if (req->out.h.error) {
                SetPageError(page);
@@ -641,52 +607,15 @@ static void write_page_end(struct fuse_conn *fc, struct fuse_req *req)
                        set_bit(AS_EIO, &page->mapping->flags);
        }
        up_read(&fi->write_sem);
-
        end_page_writeback(page);
-       kunmap(page);
        fuse_put_request(fc, req);
 }
 
-static void fuse_send_writepage(struct fuse_req *req, struct inode *inode,
-                               struct page *page, unsigned count)
-{
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_write_in *inarg;
-       struct fuse_file *ff;
-       char *buffer;
-
-       BUG_ON(list_empty(&fi->write_files));
-       ff = list_entry(fi->write_files.next, struct fuse_file, ff_list);
-       
-       inarg = &req->misc.write.in;
-       buffer = kmap(page);
-       inarg->writepage = 1;
-       inarg->fh = ff->fh;
-       inarg->offset = ((loff_t) page->index << PAGE_CACHE_SHIFT);
-       inarg->size = count;
-       req->in.h.opcode = FUSE_WRITE;
-       req->in.h.nodeid = fi->nodeid;
-       req->in.h.uid = 0;
-       req->in.h.gid = 0;
-       req->in.h.pid = 0;
-       req->in.numargs = 2;
-       req->in.args[0].size = sizeof(struct fuse_write_in);
-       req->in.args[0].value = inarg;
-       req->in.args[1].size = count;
-       req->in.args[1].value = buffer;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(struct fuse_write_out);
-       req->out.args[0].value = &req->misc.write.out;
-       req->pages[0] = page;
-       request_send_async(fc, req, write_page_end);
-}
-
 static int fuse_writepage(struct page *page, struct writeback_control *wbc)
 {
        struct inode *inode = page->mapping->host;
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        struct fuse_req *req;
        int err;
 
@@ -702,12 +631,16 @@ static int fuse_writepage(struct page *page, struct writeback_control *wbc)
                else
                        down_read(&fi->write_sem);
                if (locked) {
-                       unsigned count;
+                       unsigned count = get_write_count(inode, page);
+                       loff_t pos = (loff_t) page->index << PAGE_SHIFT;
                        err = 0;
-                       count = get_write_count(inode, page);
                        if (count) {
-                               SetPageWriteback(page);         
-                               fuse_send_writepage(req, inode, page, count);
+                               struct fuse_file *ff = get_write_file(fi);
+                               SetPageWriteback(page);
+                               fuse_write_init(req, ff, inode, pos, count, 1);
+                               req->num_pages = 1;
+                               req->pages[0] = page;
+                               request_send_async(fc, req, write_page_end);
                                goto out;
                        }
                        up_read(&fi->write_sem);
@@ -727,89 +660,34 @@ static int fuse_writepage(struct page *page, struct writeback_control *wbc)
        return err;
 }
 #else
-static ssize_t fuse_send_writepage(struct fuse_req *req, struct fuse_file *ff,
-                                  struct inode *inode, const char *buf,
-                                  loff_t pos, size_t count)
-{
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
-       struct fuse_write_in inarg;
-       struct fuse_write_out outarg;
-       ssize_t res;
-       
-       memset(&inarg, 0, sizeof(inarg));
-       inarg.writepage = 1;
-       inarg.fh = ff->fh;
-       inarg.offset = pos;
-       inarg.size = count;
-       req->in.h.opcode = FUSE_WRITE;
-       req->in.h.nodeid = fi->nodeid;
-       req->in.h.uid = 0;
-       req->in.h.gid = 0;
-       req->in.h.pid = 0;
-       req->in.numargs = 2;
-       req->in.args[0].size = sizeof(inarg);
-       req->in.args[0].value = &inarg;
-       req->in.args[1].size = count;
-       req->in.args[1].value = buf;
-       req->out.numargs = 1;
-       req->out.args[0].size = sizeof(outarg);
-       req->out.args[0].value = &outarg;
-       request_send(fc, req);
-       res = req->out.h.error;
-       if (!res) {
-               if (outarg.size > count)
-                       return -EPROTO;
-               else
-                       return outarg.size;
-       }
-       else
-               return res;
-}
-
-static int write_page_block(struct inode *inode, struct page *page)
+static int fuse_writepage(struct page *page)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       struct fuse_inode *fi = INO_FI(inode);
-       char *buffer;
-       ssize_t res;
-       loff_t pos;
+       int err;
        unsigned count;
-       struct fuse_req *req;
+       struct inode *inode = page->mapping->host;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
+       struct fuse_req *req = fuse_get_request_nonint(fc);
 
-       req = fuse_get_request(fc);
-       if (!req)
-               return -ERESTARTSYS;
-       
        down_read(&fi->write_sem);
        count = get_write_count(inode, page);
-       res = 0;
+       err = 0;
        if (count) {
-               struct fuse_file *ff;
-               BUG_ON(list_empty(&fi->write_files));
-               ff = list_entry(fi->write_files.next, struct fuse_file, ff_list);
-               pos = ((loff_t) page->index << PAGE_CACHE_SHIFT);
-               buffer = kmap(page);
-               res = fuse_send_writepage(req, ff, inode, buffer, pos, count);
-               if (res >= 0) {
-                       if (res < count) {
-                               printk("fuse: short write\n");
-                               res = -EPROTO;
-                       } else
-                               res = 0;
-               }
+               struct fuse_file *ff = get_write_file(fi);
+               loff_t pos = ((loff_t) page->index << PAGE_SHIFT);
+
+               fuse_write_init(req, ff, inode, pos, count, 1);
+               req->num_pages = 1;
+               req->pages[0] = page;
+               request_send(fc, req);
+               err = req->out.h.error;
+               if (!err && req->misc.write.out.size != count)
+                       err = -EPROTO;
        }
        up_read(&fi->write_sem);
        fuse_put_request(fc, req);
-       kunmap(page);
-       if (res)
+       if (err)
                SetPageError(page);
-       return res;
-}
-
-static int fuse_writepage(struct page *page)
-{
-       int err = write_page_block(page->mapping->host, page);
        unlock_page(page);
        return err;
 }
@@ -826,15 +704,29 @@ static int fuse_commit_write(struct file *file, struct page *page,
                             unsigned offset, unsigned to)
 {
        int err;
+       unsigned count = to - offset;
        struct inode *inode = page->mapping->host;
+       struct fuse_file *ff = file->private_data;
+       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_req *req = fuse_get_request(fc);
+       loff_t pos = ((loff_t) page->index << PAGE_SHIFT) + offset;
+       if (!req)
+               return -ERESTARTSYS;
 
-       err = write_buffer(inode, file, page, offset, to - offset);
+       fuse_write_init(req, ff, inode, pos, count, 0);
+       req->num_pages = 1;
+       req->pages[0] = page;
+       req->page_offset = offset;
+       request_send(fc, req);
+       err = req->out.h.error;
+       if (!err && req->misc.write.out.size != count)
+               err = -EPROTO;
        if (!err) {
-               loff_t pos = (page->index << PAGE_CACHE_SHIFT) + to;
+               pos += count;
                if (pos > i_size_read(inode))
                        i_size_write(inode, pos);
                
-               if (offset == 0 && to == PAGE_CACHE_SIZE) {
+               if (offset == 0 && to == PAGE_SIZE) {
 #ifdef KERNEL_2_6
                        clear_page_dirty(page);
 #else
@@ -842,8 +734,8 @@ static int fuse_commit_write(struct file *file, struct page *page,
 #endif
                        SetPageUptodate(page);
                }
-
        }
+       fuse_put_request(fc, req);
        return err;
 }
 
@@ -851,49 +743,44 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
-       char *tmpbuf;
-       ssize_t res = 0;
        loff_t pos = *ppos;
-       struct fuse_req *req;
-       size_t max_write = min(fc->max_write, (unsigned) PAGE_SIZE);
-
-       req = fuse_get_request(fc);
+       ssize_t res = 0;
+       struct fuse_req *req = fuse_get_request(fc);
        if (!req)
                return -ERESTARTSYS;
 
-       tmpbuf = (char *) __get_free_page(GFP_KERNEL);
-       if (!tmpbuf) {
-               fuse_put_request(fc, req);
-               return -ENOMEM;
-       }
-
        while (count) {
-               size_t nbytes = min(max_write, count);
-               ssize_t res1;
-               if (copy_from_user(tmpbuf, buf, nbytes)) {
-                       res = -EFAULT;
+               unsigned ntmp;
+               unsigned nwritten;
+               size_t nbytes = min(count, fc->max_write);
+               int err = fuse_get_user_pages(req, buf, nbytes, 0);
+               if (err) {
+                       res = err;
                        break;
                }
-               res1 = fuse_send_write(req, ff, inode, tmpbuf, pos, nbytes);
-               if (res1 < 0) {
-                       res = res1;
+               ntmp = (req->num_pages << PAGE_SHIFT) - req->page_offset;
+               nbytes = min(nbytes, ntmp);
+               fuse_write_init(req, ff, inode, pos, nbytes, 0);
+               request_send(fc, req);
+               fuse_release_user_pages(req, 0);
+               if (req->out.h.error) {
+                       if (!res)
+                               res = req->out.h.error;
                        break;
                }
-               res += res1;
-               count -= res1;
-               buf += res1;
-               pos += res1;
-               if (res1 < nbytes)
+               nwritten = req->misc.write.out.size;
+               count -= nwritten;
+               res += nwritten;
+               pos += nwritten;
+               buf += nwritten;
+               if (nwritten != nbytes)
                        break;
-
                if (count)
                        fuse_reset_request(req);
        }
-       free_page((unsigned long) tmpbuf);
        fuse_put_request(fc, req);
-
        if (res > 0) {
                if (pos > i_size_read(inode))
                        i_size_write(inode, pos);
@@ -907,7 +794,7 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
                               size_t count, loff_t *ppos)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
        
        if (fc->flags & FUSE_DIRECT_IO) {
                ssize_t res;
@@ -915,6 +802,7 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
                res = fuse_direct_write(file, buf, count, ppos);
                up(&inode->i_sem);
                return res;
+               return -EPERM;
        }
        else 
                return generic_file_write(file, buf, count, ppos);
@@ -923,14 +811,14 @@ static ssize_t fuse_file_write(struct file *file, const char __user *buf,
 static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct inode *inode = file->f_dentry->d_inode;
-       struct fuse_conn *fc = INO_FC(inode);
+       struct fuse_conn *fc = get_fuse_conn(inode);
 
        if (fc->flags & FUSE_DIRECT_IO)
                return -ENODEV;
        else {
                if ((vma->vm_flags & (VM_WRITE | VM_SHARED)) == 
                    (VM_WRITE | VM_SHARED)) {
-                       struct fuse_inode *fi = INO_FI(inode);
+                       struct fuse_inode *fi = get_fuse_inode(inode);
                        struct fuse_file *ff = file->private_data;
 
                        if (!user_mmap && current->uid != 0)
index 37d8cad342370079a6185114ffcbe2912246f675..b9dd4b868b112404dbe37aefba59d224e555ec81 100644 (file)
     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 */
+/** If the FUSE_KERNEL_CACHE flag is given, then cached data will not
+    be flushed on open */
 #define FUSE_KERNEL_CACHE        (1 << 2)
 
 #ifndef KERNEL_2_6
 /** Allow FUSE to combine reads into 64k chunks.  This is useful if
-    the filesystem is better at handling large chunks.  NOTE: in
-    current implementation the raw throughput is worse for large reads
-    than for small. */
+    the filesystem is better at handling large chunks */
 #define FUSE_LARGE_READ          (1 << 31)
 #endif
 /** Bypass the page cache for read and write operations  */
 
 /** FUSE specific inode data */
 struct fuse_inode {
+       /** Unique ID, which identifies the inode between userspace
+        * and kernel */
        unsigned long nodeid;
+
+       /** The request used for sending the FORGET message */
        struct fuse_req *forget_req;
+
+       /** Semaphore protects the 'write_files' list, and against
+           truncate racing with async writeouts */
        struct rw_semaphore write_sem;
+
+       /** Time in jiffies until the file attributes are valid */
        unsigned long i_time;
-       /* Files which can provide file handles in writepage.
-          Protected by write_sem  */
+
+       /* List of fuse_files which can provide file handles in
+        * writepage, protected by write_sem */
        struct list_head write_files;
 };
 
@@ -113,8 +121,16 @@ struct fuse_in_arg {
 
 /** The request input */
 struct fuse_in {
+       /** The request header */
        struct fuse_in_header h;
+       
+       /** True if the data for the last argument is in req->pages */
+       unsigned argpages:1;
+
+       /** Number of arguments */
        unsigned numargs;
+
+       /** Array of arguments */
        struct fuse_in_arg args[3];
 };
 
@@ -265,13 +281,34 @@ struct fuse_getdir_out_i {
        void *file; /* Used by kernel only */
 };
 
+static inline struct fuse_conn **get_fuse_conn_super_p(struct super_block *sb)
+{
 #ifdef KERNEL_2_6
-#define SB_FC(sb) ((sb)->s_fs_info)
+       return (struct fuse_conn **) &sb->s_fs_info;
 #else
-#define SB_FC(sb) ((sb)->u.generic_sbp)
+       return (struct fuse_conn **) &sb->u.generic_sbp;
 #endif
-#define INO_FC(inode) SB_FC((inode)->i_sb)
-#define INO_FI(i) ((struct fuse_inode *) (((struct inode *)(i))+1))
+}
+
+static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb)
+{
+       return *get_fuse_conn_super_p(sb);
+}
+
+static inline struct fuse_conn *get_fuse_conn(struct inode *inode)
+{
+       return get_fuse_conn_super(inode->i_sb);
+}
+
+static inline struct fuse_inode *get_fuse_inode(struct inode *inode)
+{
+       return (struct fuse_inode *) (&inode[1]);
+}
+
+static inline unsigned long get_node_id(struct inode *inode)
+{
+       return get_fuse_inode(inode)->nodeid;
+}
 
 /** Device operations */
 extern struct file_operations fuse_dev_operations;
index 0a70d028f43eddba74478ab53733576b40e49f1b..e0a39027d3f92f3a4a94248ea4640ec8e5fb546c 100644 (file)
@@ -65,7 +65,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
        inode->u.generic_ip = NULL;
 #endif
 
-       fi = INO_FI(inode);
+       fi = get_fuse_inode(inode);
        memset(fi, 0, sizeof(*fi));
        fi->forget_req = fuse_request_alloc();
        if (!fi->forget_req) {
@@ -80,7 +80,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
 
 static void fuse_destroy_inode(struct inode *inode)
 {
-       struct fuse_inode *fi = INO_FI(inode);
+       struct fuse_inode *fi = get_fuse_inode(inode);
        BUG_ON(!list_empty(&fi->write_files));
        if (fi->forget_req)
                fuse_request_free(fi->forget_req);
@@ -107,10 +107,9 @@ void fuse_send_forget(struct fuse_conn *fc, struct fuse_req *req,
 
 static void fuse_clear_inode(struct inode *inode)
 {
-       struct fuse_conn *fc = INO_FC(inode);
-       
+       struct fuse_conn *fc = get_fuse_conn(inode);
        if (fc) {
-               struct fuse_inode *fi = INO_FI(inode);
+               struct fuse_inode *fi = get_fuse_inode(inode);
                fuse_send_forget(fc, fi->forget_req, fi->nodeid, inode->i_version);
                fi->forget_req = NULL;
        }
@@ -118,7 +117,7 @@ static void fuse_clear_inode(struct inode *inode)
 
 static void fuse_put_super(struct super_block *sb)
 {
-       struct fuse_conn *fc = SB_FC(sb);
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        down(&fc->sb_sem);
        spin_lock(&fuse_lock);
@@ -129,7 +128,7 @@ static void fuse_put_super(struct super_block *sb)
        /* Flush all readers on this fs */
        wake_up_all(&fc->waitq);
        fuse_release_conn(fc);
-       SB_FC(sb) = NULL;
+       *get_fuse_conn_super_p(sb) = NULL;
        spin_unlock(&fuse_lock);
 }
 
@@ -148,7 +147,7 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr
 
 static int fuse_statfs(struct super_block *sb, struct kstatfs *buf)
 {
-       struct fuse_conn *fc = SB_FC(sb);
+       struct fuse_conn *fc = get_fuse_conn_super(sb);
        struct fuse_req *req;
        struct fuse_statfs_out outarg;
        int err;
@@ -289,7 +288,7 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
 
 static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
 {
-       struct fuse_conn *fc = SB_FC(mnt->mnt_sb);
+       struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
 
        seq_printf(m, ",uid=%u", fc->uid);
        if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
@@ -431,7 +430,6 @@ static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
                          int connectable)
 {
        struct inode *inode = dentry->d_inode;
-       struct fuse_inode *fi = INO_FI(inode);
        int len = *max_len;
        int type = 1;
        
@@ -439,16 +437,14 @@ static int fuse_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
                return 255;
 
        len = 2;
-       fh[0] = fi->nodeid;
+       fh[0] = get_fuse_inode(inode)->nodeid;
        fh[1] = inode->i_generation;
        if (connectable && !S_ISDIR(inode->i_mode)) {
                struct inode *parent;
-               struct fuse_inode *parent_fi;
 
                spin_lock(&dentry->d_lock);
                parent = dentry->d_parent->d_inode;
-               parent_fi = INO_FI(parent);
-               fh[2] = parent_fi->nodeid;
+               fh[2] = get_fuse_inode(parent)->nodeid;
                fh[3] = parent->i_generation;
                spin_unlock(&dentry->d_lock);
                len = 4;
@@ -517,7 +513,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
 #endif
        fc->max_write = FUSE_MAX_IN / 2;
        
-       SB_FC(sb) = fc;
+       *get_fuse_conn_super_p(sb) = fc;
 
        root = get_root_inode(sb, d.rootmode);
        if (root == NULL) {
@@ -540,7 +536,7 @@ static int fuse_read_super(struct super_block *sb, void *data, int silent)
        up(&fc->sb_sem);
        fuse_release_conn(fc);
        spin_unlock(&fuse_lock);
-       SB_FC(sb) = NULL;
+       *get_fuse_conn_super_p(sb) = NULL;
        return -EINVAL;
 }