summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-03-09 00:59:59 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2011-03-14 09:15:27 -0400
commit6c0d46c493217cf48999b3f8808910ae534aa085 (patch)
tree4c36a27f499ce8a8fb70807c78187c247e79dc65 /fs/namei.c
parentca344a894b41a133dab07dfbbdf652c053f6658c (diff)
fold __open_namei_create() and open_will_truncate() into do_last()
... and clean up a bit more Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c74
1 files changed, 26 insertions, 48 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 63844776484c..441f1106de08 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2049,30 +2049,6 @@ static int handle_truncate(struct file *filp)
}
/*
- * Be careful about ever adding any more callers of this
- * function. Its flags must be in the namei format, not
- * what get passed to sys_open().
- */
-static int __open_namei_create(struct nameidata *nd, struct path *path,
- int open_flag, int mode)
-{
- int error;
- struct dentry *dir = nd->path.dentry;
-
- if (!IS_POSIXACL(dir->d_inode))
- mode &= ~current_umask();
- error = security_path_mknod(&nd->path, path->dentry, mode, 0);
- if (error)
- goto out_unlock;
- error = vfs_create(dir->d_inode, path->dentry, mode, nd);
-out_unlock:
- mutex_unlock(&dir->d_inode->i_mutex);
- dput(nd->path.dentry);
- nd->path.dentry = path->dentry;
- return error;
-}
-
-/*
* Note that while the flag value (low two bits) for sys_open means:
* 00 - read-only
* 01 - write-only
@@ -2096,17 +2072,6 @@ static inline int open_to_namei_flags(int flag)
return flag;
}
-static int open_will_truncate(int flag, struct inode *inode)
-{
- /*
- * We'll never write to the fs underlying
- * a device file.
- */
- if (special_file(inode->i_mode))
- return 0;
- return (flag & O_TRUNC);
-}
-
/*
* Handle the last step of open()
*/
@@ -2114,8 +2079,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
const struct open_flags *op, const char *pathname)
{
struct dentry *dir = nd->path.dentry;
+ struct dentry *dentry;
int open_flag = op->open_flag;
- int will_truncate;
+ int will_truncate = open_flag & O_TRUNC;
int want_write = 0;
int skip_perm = 0;
struct file *filp;
@@ -2207,25 +2173,29 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
mutex_lock(&dir->d_inode->i_mutex);
- path->dentry = lookup_hash(nd);
- path->mnt = nd->path.mnt;
-
- error = PTR_ERR(path->dentry);
- if (IS_ERR(path->dentry)) {
+ dentry = lookup_hash(nd);
+ error = PTR_ERR(dentry);
+ if (IS_ERR(dentry)) {
mutex_unlock(&dir->d_inode->i_mutex);
goto exit;
}
+ path->dentry = dentry;
+ path->mnt = nd->path.mnt;
+
if (IS_ERR(nd->intent.open.file)) {
error = PTR_ERR(nd->intent.open.file);
goto exit_mutex_unlock;
}
/* Negative dentry, just create the file */
- if (!path->dentry->d_inode) {
+ if (!dentry->d_inode) {
+ int mode = op->mode;
+ if (!IS_POSIXACL(dir->d_inode))
+ mode &= ~current_umask();
/*
* This write is needed to ensure that a
- * ro->rw transition does not occur between
+ * rw->ro transition does not occur between
* the time when the file is created and when
* a permanent write count is taken through
* the 'struct file' in nameidata_to_filp().
@@ -2234,13 +2204,19 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (error)
goto exit_mutex_unlock;
want_write = 1;
- will_truncate = 0;
- error = __open_namei_create(nd, path, open_flag, op->mode);
- if (error)
- goto exit;
/* Don't check for write permission, don't truncate */
open_flag &= ~O_TRUNC;
+ will_truncate = 0;
skip_perm = 1;
+ error = security_path_mknod(&nd->path, dentry, mode, 0);
+ if (error)
+ goto exit_mutex_unlock;
+ error = vfs_create(dir->d_inode, dentry, mode, nd);
+ if (error)
+ goto exit_mutex_unlock;
+ mutex_unlock(&dir->d_inode->i_mutex);
+ dput(nd->path.dentry);
+ nd->path.dentry = dentry;
goto common;
}
@@ -2271,7 +2247,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (S_ISDIR(nd->inode->i_mode))
goto exit;
ok:
- will_truncate = open_will_truncate(open_flag, nd->path.dentry->d_inode);
+ if (!S_ISREG(nd->inode->i_mode))
+ will_truncate = 0;
+
if (will_truncate) {
error = mnt_want_write(nd->path.mnt);
if (error)