forked from Minki/linux
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>
This commit is contained in:
parent
ca344a894b
commit
6c0d46c493
74
fs/namei.c
74
fs/namei.c
@ -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
|
||||
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user