mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 06:40:54 +07:00
vfs: add lookup_open()
Split out lookup + maybe create from do_last(). This is the part under i_mutex protection. The function is called lookup_open() and returns a filp even though the open part is not used yet. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
7157486541
commit
d58ffd35c1
99
fs/namei.c
99
fs/namei.c
@ -2196,6 +2196,60 @@ static inline int open_to_namei_flags(int flag)
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup, maybe create and open the last component
|
||||||
|
*
|
||||||
|
* Must be called with i_mutex held on parent.
|
||||||
|
*
|
||||||
|
* Returns open file or NULL on success, error otherwise. NULL means no open
|
||||||
|
* was performed, only lookup.
|
||||||
|
*/
|
||||||
|
static struct file *lookup_open(struct nameidata *nd, struct path *path,
|
||||||
|
const struct open_flags *op,
|
||||||
|
int *want_write, bool *created)
|
||||||
|
{
|
||||||
|
struct dentry *dir = nd->path.dentry;
|
||||||
|
struct dentry *dentry;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
*created = false;
|
||||||
|
dentry = lookup_hash(nd);
|
||||||
|
if (IS_ERR(dentry))
|
||||||
|
return ERR_CAST(dentry);
|
||||||
|
|
||||||
|
/* Negative dentry, just create the file */
|
||||||
|
if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
|
||||||
|
umode_t mode = op->mode;
|
||||||
|
if (!IS_POSIXACL(dir->d_inode))
|
||||||
|
mode &= ~current_umask();
|
||||||
|
/*
|
||||||
|
* This write is needed to ensure that a
|
||||||
|
* 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().
|
||||||
|
*/
|
||||||
|
error = mnt_want_write(nd->path.mnt);
|
||||||
|
if (error)
|
||||||
|
goto out_dput;
|
||||||
|
*want_write = 1;
|
||||||
|
*created = true;
|
||||||
|
error = security_path_mknod(&nd->path, dentry, mode, 0);
|
||||||
|
if (error)
|
||||||
|
goto out_dput;
|
||||||
|
error = vfs_create(dir->d_inode, dentry, mode, nd);
|
||||||
|
if (error)
|
||||||
|
goto out_dput;
|
||||||
|
}
|
||||||
|
path->dentry = dentry;
|
||||||
|
path->mnt = nd->path.mnt;
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out_dput:
|
||||||
|
dput(dentry);
|
||||||
|
return ERR_PTR(error);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle the last step of open()
|
* Handle the last step of open()
|
||||||
*/
|
*/
|
||||||
@ -2203,13 +2257,13 @@ 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 = open_flag & O_TRUNC;
|
int will_truncate = open_flag & O_TRUNC;
|
||||||
int want_write = 0;
|
int want_write = 0;
|
||||||
int acc_mode = op->acc_mode;
|
int acc_mode = op->acc_mode;
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
|
bool created;
|
||||||
int symlink_ok = 0;
|
int symlink_ok = 0;
|
||||||
struct path save_parent = { .dentry = NULL, .mnt = NULL };
|
struct path save_parent = { .dentry = NULL, .mnt = NULL };
|
||||||
bool retried = false;
|
bool retried = false;
|
||||||
@ -2277,53 +2331,24 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
|||||||
|
|
||||||
retry_lookup:
|
retry_lookup:
|
||||||
mutex_lock(&dir->d_inode->i_mutex);
|
mutex_lock(&dir->d_inode->i_mutex);
|
||||||
|
filp = lookup_open(nd, path, op, &want_write, &created);
|
||||||
|
mutex_unlock(&dir->d_inode->i_mutex);
|
||||||
|
|
||||||
dentry = lookup_hash(nd);
|
if (IS_ERR(filp))
|
||||||
error = PTR_ERR(dentry);
|
goto out;
|
||||||
if (IS_ERR(dentry)) {
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
path->dentry = dentry;
|
if (created) {
|
||||||
path->mnt = nd->path.mnt;
|
|
||||||
|
|
||||||
/* Negative dentry, just create the file */
|
|
||||||
if (!dentry->d_inode && (open_flag & O_CREAT)) {
|
|
||||||
umode_t mode = op->mode;
|
|
||||||
if (!IS_POSIXACL(dir->d_inode))
|
|
||||||
mode &= ~current_umask();
|
|
||||||
/*
|
|
||||||
* This write is needed to ensure that a
|
|
||||||
* 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().
|
|
||||||
*/
|
|
||||||
error = mnt_want_write(nd->path.mnt);
|
|
||||||
if (error)
|
|
||||||
goto exit_mutex_unlock;
|
|
||||||
want_write = 1;
|
|
||||||
/* 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;
|
will_truncate = 0;
|
||||||
acc_mode = MAY_OPEN;
|
acc_mode = MAY_OPEN;
|
||||||
error = security_path_mknod(&nd->path, dentry, mode, 0);
|
path_to_nameidata(path, nd);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It already exists.
|
* It already exists.
|
||||||
*/
|
*/
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
|
||||||
audit_inode(pathname, path->dentry);
|
audit_inode(pathname, path->dentry);
|
||||||
|
|
||||||
error = -EEXIST;
|
error = -EEXIST;
|
||||||
@ -2432,8 +2457,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
|
|||||||
terminate_walk(nd);
|
terminate_walk(nd);
|
||||||
return filp;
|
return filp;
|
||||||
|
|
||||||
exit_mutex_unlock:
|
|
||||||
mutex_unlock(&dir->d_inode->i_mutex);
|
|
||||||
exit_dput:
|
exit_dput:
|
||||||
path_put_conditional(path, nd);
|
path_put_conditional(path, nd);
|
||||||
exit:
|
exit:
|
||||||
|
Loading…
Reference in New Issue
Block a user