fix vfsmount leak bug in fuse_follow_link
authorMiklos Szeredi <miklos@szeredi.hu>
Tue, 13 Nov 2001 16:11:35 +0000 (16:11 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Tue, 13 Nov 2001 16:11:35 +0000 (16:11 +0000)
include/fuse.h
include/linux/fuse.h
kernel/dir.c
kernel/inode.c
lib/fuse.c

index a1172111a0098ab915e46dd89e574a726037c590..60cd37844267ba7f4c8ca6708591e3d8f5b255ad 100644 (file)
@@ -30,6 +30,11 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t, const char *, int type);
  *  - All operations should return the negated error value (-errno) on
  *  error.
  * 
+ *  - Getattr() doesn't need to fill in the following fields:
+ *      st_ino
+ *      st_dev
+ *      st_blksize
+ * 
  *  - readlink() should fill the buffer with a null terminated string.  The
  *  buffer size argument includes the space for the terminating null
  *  character.  If the linkname is too long to fit in the buffer, it should
index d41a957ce76a960c5c8edbfbf690e622bd23a64c..0cd9e5c227ddddf912391cb710a8340171a1a9c4 100644 (file)
@@ -42,7 +42,7 @@ struct fuse_attr {
        unsigned int        gid;
        unsigned int        rdev;
        unsigned long long  size;
-       unsigned long       blksize;
+       unsigned long       _dummy;
        unsigned long       blocks;
        unsigned long       atime;
        unsigned long       mtime;
index cd6394a68e9eb133bcc747a4d5cf389e43913620..8c60afad2b79fbad27e753281d3689759baa81c8 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "fuse_i.h"
 
+#include <linux/pagemap.h>
 #include <linux/slab.h>
 #include <linux/file.h>
 
@@ -32,7 +33,7 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_uid     = attr->uid;
        inode->i_gid     = attr->gid;
        inode->i_size    = attr->size;
-       inode->i_blksize = attr->blksize;
+       inode->i_blksize = PAGE_CACHE_SIZE;
        inode->i_blocks  = attr->blocks;
        inode->i_atime   = attr->atime;
        inode->i_mtime   = attr->mtime;
@@ -385,37 +386,37 @@ static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir)
        return ret;
 }
 
-static int read_link(struct dentry *dentry, char **bufp)
+static char *read_link(struct dentry *dentry)
 {
        struct inode *inode = dentry->d_inode;
        struct fuse_conn *fc = INO_FC(inode);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
-       unsigned long page;
+       char *link;
 
-       page = __get_free_page(GFP_KERNEL);
-       if(!page)
-               return -ENOMEM;
+       link = (char *) __get_free_page(GFP_KERNEL);
+       if(!link)
+               return ERR_PTR(-ENOMEM);
 
        in.h.opcode = FUSE_READLINK;
        in.h.ino = inode->i_ino;
-       out.arg = (void *) page;
+       out.arg = link;
        out.argsize = PAGE_SIZE - 1;
        out.argvar = 1;
        request_send(fc, &in, &out);
        if(out.h.error) {
-               free_page(page);
-               return out.h.error;
+               free_page((unsigned long) link);
+               return ERR_PTR(out.h.error);
        }
 
-       *bufp = (char *) page;
-       (*bufp)[out.argsize] = '\0';
-       return 0;
+       link[out.argsize] = '\0';
+       return link;
 }
 
 static void free_link(char *link)
 {
-       free_page((unsigned long) link);
+       if(!IS_ERR(link))
+               free_page((unsigned long) link);
 }
 
 static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
@@ -423,10 +424,7 @@ static int fuse_readlink(struct dentry *dentry, char *buffer, int buflen)
        int ret;
        char *link;
 
-       ret = read_link(dentry, &link);
-       if(ret)
-               return ret;
-
+       link = read_link(dentry);
        ret = vfs_readlink(dentry, buffer, buflen, link);
        free_link(link);
        return ret;
@@ -437,10 +435,7 @@ static int fuse_follow_link(struct dentry *dentry, struct nameidata *nd)
        int ret;
        char *link;
 
-       ret = read_link(dentry, &link);
-       if(ret)
-               return ret;
-
+       link = read_link(dentry);
        ret = vfs_follow_link(nd, link);
        free_link(link);
        return ret;
@@ -550,8 +545,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, int flags)
 {
        if(!entry->d_inode)
                return 0;
-       else if(!(flags & LOOKUP_CONTINUE) && 
-               time_after(jiffies, entry->d_time + FUSE_REVALIDATE_TIME))
+       else if(!(flags & LOOKUP_CONTINUE))
                return 0;
        else
                return 1;
index 3a780403f2fdeb359150a55b1c88ebe29824cac6..36819b732c0a6bfa0580c98e0ed8caa7dcc094f3 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "fuse_i.h"
 
+#include <linux/pagemap.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/file.h>
@@ -104,8 +105,8 @@ static struct super_block *fuse_read_super(struct super_block *sb,
        struct inode *root;
        struct fuse_mount_data *d = data;
 
-        sb->s_blocksize = 1024;
-        sb->s_blocksize_bits = 10;
+        sb->s_blocksize = PAGE_CACHE_SIZE;
+        sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
         sb->s_magic = FUSE_SUPER_MAGIC;
         sb->s_op = &fuse_super_operations;
 
index 3f8a46bc22d87a902b78863d558775480b13697f..e042c4ab2fe04a24a61c265fd62b06df927a1a95 100644 (file)
@@ -297,7 +297,6 @@ static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
     attr->gid     = stbuf->st_gid;
     attr->rdev    = stbuf->st_rdev;
     attr->size    = stbuf->st_size;
-    attr->blksize = stbuf->st_blksize;
     attr->blocks  = stbuf->st_blocks;
     attr->atime   = stbuf->st_atime;
     attr->mtime   = stbuf->st_mtime;