diff options
author | Dave Hansen <haveblue@us.ibm.com> | 2008-02-15 14:37:26 -0800 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-03-19 06:54:05 -0400 |
commit | 430e285e0817e3e18aadd814bc078d50d8af0cbf (patch) | |
tree | cbd008864e18e76a7e2984bfd1898028762fd19a | |
parent | 322ee5b36eac42e762526b0df7fa432beba6e7a0 (diff) | |
download | lwn-430e285e0817e3e18aadd814bc078d50d8af0cbf.tar.gz lwn-430e285e0817e3e18aadd814bc078d50d8af0cbf.zip |
[PATCH] fix up new filp allocators
Some new uses of get_empty_filp() have crept in; switched
to alloc_file() to make sure that pieces of initialization
won't be missing.
We really need to kill get_empty_filp().
[AV] fixed dentry leak on failure exit in anon_inode_getfd()
Cc: Erez Zadok <ezk@cs.sunysb.edu>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: "J Bruce Fields" <bfields@fieldses.org>
Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/anon_inodes.c | 18 | ||||
-rw-r--r-- | fs/file_table.c | 6 | ||||
-rw-r--r-- | fs/pipe.c | 19 |
3 files changed, 23 insertions, 20 deletions
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 23321889d9b0..f42be069e085 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c @@ -81,13 +81,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, if (IS_ERR(anon_inode_inode)) return -ENODEV; - file = get_empty_filp(); - if (!file) - return -ENFILE; error = get_unused_fd(); if (error < 0) - goto err_put_filp; + return error; fd = error; /* @@ -114,14 +111,15 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, anon_inode_inode); - file->f_path.mnt = mntget(anon_inode_mnt); - file->f_path.dentry = dentry; + error = -ENFILE; + file = alloc_file(anon_inode_mnt, dentry, + FMODE_READ | FMODE_WRITE, fops); + if (!file) + goto err_dput; file->f_mapping = anon_inode_inode->i_mapping; file->f_pos = 0; file->f_flags = O_RDWR; - file->f_op = fops; - file->f_mode = FMODE_READ | FMODE_WRITE; file->f_version = 0; file->private_data = priv; @@ -132,10 +130,10 @@ int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile, *pfile = file; return 0; +err_dput: + dput(dentry); err_put_unused_fd: put_unused_fd(fd); -err_put_filp: - put_filp(file); return error; } EXPORT_SYMBOL_GPL(anon_inode_getfd); diff --git a/fs/file_table.c b/fs/file_table.c index 6d27befe2d48..986ff4ed0a7c 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -83,6 +83,12 @@ int proc_nr_files(ctl_table *table, int write, struct file *filp, /* Find an unused file structure and return a pointer to it. * Returns NULL, if there are no more free file structures or * we run out of memory. + * + * Be very careful using this. You are responsible for + * getting write access to any mount that you might assign + * to this filp, if it is opened for write. If this is not + * done, you will imbalance int the mount's writer count + * and a warning at __fput() time. */ struct file *get_empty_filp(void) { diff --git a/fs/pipe.c b/fs/pipe.c index 3c185b6527bc..8be381bbcb54 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -957,13 +957,10 @@ struct file *create_write_pipe(void) struct dentry *dentry; struct qstr name = { .name = "" }; - f = get_empty_filp(); - if (!f) - return ERR_PTR(-ENFILE); err = -ENFILE; inode = get_pipe_inode(); if (!inode) - goto err_file; + goto err; err = -ENOMEM; dentry = d_alloc(pipe_mnt->mnt_sb->s_root, &name); @@ -978,22 +975,24 @@ struct file *create_write_pipe(void) */ dentry->d_flags &= ~DCACHE_UNHASHED; d_instantiate(dentry, inode); - f->f_path.mnt = mntget(pipe_mnt); - f->f_path.dentry = dentry; + + err = -ENFILE; + f = alloc_file(pipe_mnt, dentry, FMODE_WRITE, &write_pipe_fops); + if (!f) + goto err_dentry; f->f_mapping = inode->i_mapping; f->f_flags = O_WRONLY; - f->f_op = &write_pipe_fops; - f->f_mode = FMODE_WRITE; f->f_version = 0; return f; + err_dentry: + dput(dentry); err_inode: free_pipe_info(inode); iput(inode); - err_file: - put_filp(f); + err: return ERR_PTR(err); } |