Commit a70e65df authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Al Viro

[PATCH] merge open_namei() and do_filp_open()

open_namei() will, in the future, need to take mount write counts
over its creation and truncation (via may_open()) operations.  It
needs to keep these write counts until any potential filp that is
created gets __fput()'d.

This gets complicated in the error handling and becomes very murky
as to how far open_namei() actually got, and whether or not that
mount write count was taken.  That makes it a bad interface.

All that the current do_filp_open() really does is allocate the
nameidata on the stack, then call open_namei().

So, this merges those two functions and moves filp_open() over
to namei.c so it can be close to its buddy: do_filp_open().  It
also gets a kerneldoc comment in the process.
Acked-by: default avatarAl Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarDave Hansen <haveblue@us.ibm.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d57999e1
...@@ -1725,17 +1725,13 @@ static inline int open_to_namei_flags(int flag) ...@@ -1725,17 +1725,13 @@ static inline int open_to_namei_flags(int flag)
} }
/* /*
* open_namei()
*
* namei for open - this is in fact almost the whole open-routine.
*
* Note that the low bits of "flag" aren't the same as in the open * Note that the low bits of "flag" aren't the same as in the open
* system call. See open_to_namei_flags(). * system call. See open_to_namei_flags().
* SMP-safe
*/ */
int open_namei(int dfd, const char *pathname, int open_flag, struct file *do_filp_open(int dfd, const char *pathname,
int mode, struct nameidata *nd) int open_flag, int mode)
{ {
struct nameidata nd;
int acc_mode, error; int acc_mode, error;
struct path path; struct path path;
struct dentry *dir; struct dentry *dir;
...@@ -1758,18 +1754,19 @@ int open_namei(int dfd, const char *pathname, int open_flag, ...@@ -1758,18 +1754,19 @@ int open_namei(int dfd, const char *pathname, int open_flag,
*/ */
if (!(flag & O_CREAT)) { if (!(flag & O_CREAT)) {
error = path_lookup_open(dfd, pathname, lookup_flags(flag), error = path_lookup_open(dfd, pathname, lookup_flags(flag),
nd, flag); &nd, flag);
if (error) if (error)
return error; return ERR_PTR(error);
goto ok; goto ok;
} }
/* /*
* Create - we need to know the parent. * Create - we need to know the parent.
*/ */
error = path_lookup_create(dfd,pathname,LOOKUP_PARENT,nd,flag,mode); error = path_lookup_create(dfd, pathname, LOOKUP_PARENT,
&nd, flag, mode);
if (error) if (error)
return error; return ERR_PTR(error);
/* /*
* We have the parent and last component. First of all, check * We have the parent and last component. First of all, check
...@@ -1777,14 +1774,14 @@ int open_namei(int dfd, const char *pathname, int open_flag, ...@@ -1777,14 +1774,14 @@ int open_namei(int dfd, const char *pathname, int open_flag,
* will not do. * will not do.
*/ */
error = -EISDIR; error = -EISDIR;
if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len]) if (nd.last_type != LAST_NORM || nd.last.name[nd.last.len])
goto exit; goto exit;
dir = nd->path.dentry; dir = nd.path.dentry;
nd->flags &= ~LOOKUP_PARENT; nd.flags &= ~LOOKUP_PARENT;
mutex_lock(&dir->d_inode->i_mutex); mutex_lock(&dir->d_inode->i_mutex);
path.dentry = lookup_hash(nd); path.dentry = lookup_hash(&nd);
path.mnt = nd->path.mnt; path.mnt = nd.path.mnt;
do_last: do_last:
error = PTR_ERR(path.dentry); error = PTR_ERR(path.dentry);
...@@ -1793,18 +1790,18 @@ do_last: ...@@ -1793,18 +1790,18 @@ do_last:
goto exit; goto exit;
} }
if (IS_ERR(nd->intent.open.file)) { if (IS_ERR(nd.intent.open.file)) {
mutex_unlock(&dir->d_inode->i_mutex); mutex_unlock(&dir->d_inode->i_mutex);
error = PTR_ERR(nd->intent.open.file); error = PTR_ERR(nd.intent.open.file);
goto exit_dput; goto exit_dput;
} }
/* Negative dentry, just create the file */ /* Negative dentry, just create the file */
if (!path.dentry->d_inode) { if (!path.dentry->d_inode) {
error = __open_namei_create(nd, &path, flag, mode); error = __open_namei_create(&nd, &path, flag, mode);
if (error) if (error)
goto exit; goto exit;
return 0; return nameidata_to_filp(&nd, open_flag);
} }
/* /*
...@@ -1829,23 +1826,23 @@ do_last: ...@@ -1829,23 +1826,23 @@ do_last:
if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link) if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
goto do_link; goto do_link;
path_to_nameidata(&path, nd); path_to_nameidata(&path, &nd);
error = -EISDIR; error = -EISDIR;
if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode)) if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
goto exit; goto exit;
ok: ok:
error = may_open(nd, acc_mode, flag); error = may_open(&nd, acc_mode, flag);
if (error) if (error)
goto exit; goto exit;
return 0; return nameidata_to_filp(&nd, open_flag);
exit_dput: exit_dput:
path_put_conditional(&path, nd); path_put_conditional(&path, &nd);
exit: exit:
if (!IS_ERR(nd->intent.open.file)) if (!IS_ERR(nd.intent.open.file))
release_open_intent(nd); release_open_intent(&nd);
path_put(&nd->path); path_put(&nd.path);
return error; return ERR_PTR(error);
do_link: do_link:
error = -ELOOP; error = -ELOOP;
...@@ -1861,42 +1858,59 @@ do_link: ...@@ -1861,42 +1858,59 @@ do_link:
* stored in nd->last.name and we will have to putname() it when we * stored in nd->last.name and we will have to putname() it when we
* are done. Procfs-like symlinks just set LAST_BIND. * are done. Procfs-like symlinks just set LAST_BIND.
*/ */
nd->flags |= LOOKUP_PARENT; nd.flags |= LOOKUP_PARENT;
error = security_inode_follow_link(path.dentry, nd); error = security_inode_follow_link(path.dentry, &nd);
if (error) if (error)
goto exit_dput; goto exit_dput;
error = __do_follow_link(&path, nd); error = __do_follow_link(&path, &nd);
if (error) { if (error) {
/* Does someone understand code flow here? Or it is only /* Does someone understand code flow here? Or it is only
* me so stupid? Anathema to whoever designed this non-sense * me so stupid? Anathema to whoever designed this non-sense
* with "intent.open". * with "intent.open".
*/ */
release_open_intent(nd); release_open_intent(&nd);
return error; return ERR_PTR(error);
} }
nd->flags &= ~LOOKUP_PARENT; nd.flags &= ~LOOKUP_PARENT;
if (nd->last_type == LAST_BIND) if (nd.last_type == LAST_BIND)
goto ok; goto ok;
error = -EISDIR; error = -EISDIR;
if (nd->last_type != LAST_NORM) if (nd.last_type != LAST_NORM)
goto exit; goto exit;
if (nd->last.name[nd->last.len]) { if (nd.last.name[nd.last.len]) {
__putname(nd->last.name); __putname(nd.last.name);
goto exit; goto exit;
} }
error = -ELOOP; error = -ELOOP;
if (count++==32) { if (count++==32) {
__putname(nd->last.name); __putname(nd.last.name);
goto exit; goto exit;
} }
dir = nd->path.dentry; dir = nd.path.dentry;
mutex_lock(&dir->d_inode->i_mutex); mutex_lock(&dir->d_inode->i_mutex);
path.dentry = lookup_hash(nd); path.dentry = lookup_hash(&nd);
path.mnt = nd->path.mnt; path.mnt = nd.path.mnt;
__putname(nd->last.name); __putname(nd.last.name);
goto do_last; goto do_last;
} }
/**
* filp_open - open file and return file pointer
*
* @filename: path to open
* @flags: open flags as per the open(2) second argument
* @mode: mode for the new file if O_CREAT is set, else ignored
*
* This is the helper to open a file from kernelspace if you really
* have to. But in generally you should not do this, so please move
* along, nothing to see here..
*/
struct file *filp_open(const char *filename, int flags, int mode)
{
return do_filp_open(AT_FDCWD, filename, flags, mode);
}
EXPORT_SYMBOL(filp_open);
/** /**
* lookup_create - lookup a dentry, creating it if it doesn't exist * lookup_create - lookup a dentry, creating it if it doesn't exist
* @nd: nameidata info * @nd: nameidata info
......
...@@ -796,25 +796,6 @@ cleanup_file: ...@@ -796,25 +796,6 @@ cleanup_file:
return ERR_PTR(error); return ERR_PTR(error);
} }
static struct file *do_filp_open(int dfd, const char *filename, int flags,
int mode)
{
int error;
struct nameidata nd;
error = open_namei(dfd, filename, flags, mode, &nd);
if (!error)
return nameidata_to_filp(&nd, flags);
return ERR_PTR(error);
}
struct file *filp_open(const char *filename, int flags, int mode)
{
return do_filp_open(AT_FDCWD, filename, flags, mode);
}
EXPORT_SYMBOL(filp_open);
/** /**
* lookup_instantiate_filp - instantiates the open intent filp * lookup_instantiate_filp - instantiates the open intent filp
* @nd: pointer to nameidata * @nd: pointer to nameidata
......
...@@ -1735,7 +1735,8 @@ extern struct file *create_read_pipe(struct file *f); ...@@ -1735,7 +1735,8 @@ extern struct file *create_read_pipe(struct file *f);
extern struct file *create_write_pipe(void); extern struct file *create_write_pipe(void);
extern void free_write_pipe(struct file *); extern void free_write_pipe(struct file *);
extern int open_namei(int dfd, const char *, int, int, struct nameidata *); extern struct file *do_filp_open(int dfd, const char *pathname,
int open_flag, int mode);
extern int may_open(struct nameidata *, int, int); extern int may_open(struct nameidata *, int, int);
extern int kernel_read(struct file *, unsigned long, char *, unsigned long); extern int kernel_read(struct file *, unsigned long, char *, unsigned long);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment