Skip to content

Commit

Permalink
fold __open_namei_create() and open_will_truncate() into do_last()
Browse files Browse the repository at this point in the history
... and clean up a bit more

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
  • Loading branch information
Al Viro committed Mar 14, 2011
1 parent ca344a8 commit 6c0d46c
Showing 1 changed file with 26 additions and 48 deletions.
74 changes: 26 additions & 48 deletions fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2048,30 +2048,6 @@ static int handle_truncate(struct file *filp)
return error;
}

/*
* 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
Expand All @@ -2096,26 +2072,16 @@ 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()
*/
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;
Expand Down Expand Up @@ -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().
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 6c0d46c

Please sign in to comment.