aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2001-11-13 16:11:35 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2001-11-13 16:11:35 +0000
commit05033041285858d581b05617900e2921502bf434 (patch)
tree11441248c4949cbdc86be73459d8b07dc80c0eff
parent0a7077f5364454de39fb1ac486d4bd233aa11798 (diff)
fix vfsmount leak bug in fuse_follow_link
-rw-r--r--include/fuse.h5
-rw-r--r--include/linux/fuse.h2
-rw-r--r--kernel/dir.c40
-rw-r--r--kernel/inode.c5
-rw-r--r--lib/fuse.c1
5 files changed, 26 insertions, 27 deletions
diff --git a/include/fuse.h b/include/fuse.h
index a117211..60cd378 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -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
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index d41a957..0cd9e5c 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -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;
diff --git a/kernel/dir.c b/kernel/dir.c
index cd6394a..8c60afa 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -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;
diff --git a/kernel/inode.c b/kernel/inode.c
index 3a78040..36819b7 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -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;
diff --git a/lib/fuse.c b/lib/fuse.c
index 3f8a46b..e042c4a 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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;