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
1 changed files with 26 additions and 48 deletions
74
fs/namei.c
74
fs/namei.c
|
@ -2048,30 +2048,6 @@ static int handle_truncate(struct file *filp)
|
||||||
return error;
|
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:
|
* Note that while the flag value (low two bits) for sys_open means:
|
||||||
* 00 - read-only
|
* 00 - read-only
|
||||||
|
@ -2096,17 +2072,6 @@ static inline int open_to_namei_flags(int flag)
|
||||||
return 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()
|
* 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)
|
const struct open_flags *op, const char *pathname)
|
||||||
{
|
{
|
||||||
struct dentry *dir = nd->path.dentry;
|
struct dentry *dir = nd->path.dentry;
|
||||||
|
struct dentry *dentry;
|
||||||
int open_flag = op->open_flag;
|
int open_flag = op->open_flag;
|
||||||
int will_truncate;
|
int will_truncate = open_flag & O_TRUNC;
|
||||||
int want_write = 0;
|
int want_write = 0;
|
||||||
int skip_perm = 0;
|
int skip_perm = 0;
|
||||||
struct file *filp;
|
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);
|
mutex_lock(&dir->d_inode->i_mutex);
|
||||||
|
|
||||||
path->dentry = lookup_hash(nd);
|
dentry = lookup_hash(nd);
|
||||||
path->mnt = nd->path.mnt;
|
error = PTR_ERR(dentry);
|
||||||
|
if (IS_ERR(dentry)) {
|
||||||
error = PTR_ERR(path->dentry);
|
|
||||||
if (IS_ERR(path->dentry)) {
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path->dentry = dentry;
|
||||||
|
path->mnt = nd->path.mnt;
|
||||||
|
|
||||||
if (IS_ERR(nd->intent.open.file)) {
|
if (IS_ERR(nd->intent.open.file)) {
|
||||||
error = PTR_ERR(nd->intent.open.file);
|
error = PTR_ERR(nd->intent.open.file);
|
||||||
goto exit_mutex_unlock;
|
goto exit_mutex_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Negative dentry, just create the file */
|
/* 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
|
* 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
|
* the time when the file is created and when
|
||||||
* a permanent write count is taken through
|
* a permanent write count is taken through
|
||||||
* the 'struct file' in nameidata_to_filp().
|
* the 'struct file' in nameidata_to_filp().
|
||||||
|
@ -2234,13 +2204,19 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
||||||
if (error)
|
if (error)
|
||||||
goto exit_mutex_unlock;
|
goto exit_mutex_unlock;
|
||||||
want_write = 1;
|
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 */
|
/* Don't check for write permission, don't truncate */
|
||||||
open_flag &= ~O_TRUNC;
|
open_flag &= ~O_TRUNC;
|
||||||
|
will_truncate = 0;
|
||||||
skip_perm = 1;
|
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;
|
goto common;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2271,7 +2247,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
||||||
if (S_ISDIR(nd->inode->i_mode))
|
if (S_ISDIR(nd->inode->i_mode))
|
||||||
goto exit;
|
goto exit;
|
||||||
ok:
|
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) {
|
if (will_truncate) {
|
||||||
error = mnt_want_write(nd->path.mnt);
|
error = mnt_want_write(nd->path.mnt);
|
||||||
if (error)
|
if (error)
|
||||||
|
|
Loading…
Add table
Reference in a new issue