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

[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
Loading
Loading
Loading
Loading
+57 −43
Original line number Diff line number Diff line
@@ -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
 * system call.  See open_to_namei_flags().
 * SMP-safe
 */
int open_namei(int dfd, const char *pathname, int open_flag,
		int mode, struct nameidata *nd)
struct file *do_filp_open(int dfd, const char *pathname,
		int open_flag, int mode)
{
	struct nameidata nd;
	int acc_mode, error;
	struct path path;
	struct dentry *dir;
@@ -1758,18 +1754,19 @@ int open_namei(int dfd, const char *pathname, int open_flag,
	 */
	if (!(flag & O_CREAT)) {
		error = path_lookup_open(dfd, pathname, lookup_flags(flag),
					 nd, flag);
					 &nd, flag);
		if (error)
			return error;
			return ERR_PTR(error);
		goto ok;
	}

	/*
	 * 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)
		return error;
		return ERR_PTR(error);

	/*
	 * 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,
	 * will not do.
	 */
	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;

	dir = nd->path.dentry;
	nd->flags &= ~LOOKUP_PARENT;
	dir = nd.path.dentry;
	nd.flags &= ~LOOKUP_PARENT;
	mutex_lock(&dir->d_inode->i_mutex);
	path.dentry = lookup_hash(nd);
	path.mnt = nd->path.mnt;
	path.dentry = lookup_hash(&nd);
	path.mnt = nd.path.mnt;

do_last:
	error = PTR_ERR(path.dentry);
@@ -1793,18 +1790,18 @@ int open_namei(int dfd, const char *pathname, int open_flag,
		goto exit;
	}

	if (IS_ERR(nd->intent.open.file)) {
	if (IS_ERR(nd.intent.open.file)) {
		mutex_unlock(&dir->d_inode->i_mutex);
		error = PTR_ERR(nd->intent.open.file);
		error = PTR_ERR(nd.intent.open.file);
		goto exit_dput;
	}

	/* Negative dentry, just create the file */
	if (!path.dentry->d_inode) {
		error = __open_namei_create(nd, &path, flag, mode);
		error = __open_namei_create(&nd, &path, flag, mode);
		if (error)
			goto exit;
		return 0;
		return nameidata_to_filp(&nd, open_flag);
	}

	/*
@@ -1829,23 +1826,23 @@ int open_namei(int dfd, const char *pathname, int open_flag,
	if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
		goto do_link;

	path_to_nameidata(&path, nd);
	path_to_nameidata(&path, &nd);
	error = -EISDIR;
	if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
		goto exit;
ok:
	error = may_open(nd, acc_mode, flag);
	error = may_open(&nd, acc_mode, flag);
	if (error)
		goto exit;
	return 0;
	return nameidata_to_filp(&nd, open_flag);

exit_dput:
	path_put_conditional(&path, nd);
	path_put_conditional(&path, &nd);
exit:
	if (!IS_ERR(nd->intent.open.file))
		release_open_intent(nd);
	path_put(&nd->path);
	return error;
	if (!IS_ERR(nd.intent.open.file))
		release_open_intent(&nd);
	path_put(&nd.path);
	return ERR_PTR(error);

do_link:
	error = -ELOOP;
@@ -1861,42 +1858,59 @@ int open_namei(int dfd, const char *pathname, int open_flag,
	 * stored in nd->last.name and we will have to putname() it when we
	 * are done. Procfs-like symlinks just set LAST_BIND.
	 */
	nd->flags |= LOOKUP_PARENT;
	error = security_inode_follow_link(path.dentry, nd);
	nd.flags |= LOOKUP_PARENT;
	error = security_inode_follow_link(path.dentry, &nd);
	if (error)
		goto exit_dput;
	error = __do_follow_link(&path, nd);
	error = __do_follow_link(&path, &nd);
	if (error) {
		/* Does someone understand code flow here? Or it is only
		 * me so stupid? Anathema to whoever designed this non-sense
		 * with "intent.open".
		 */
		release_open_intent(nd);
		return error;
		release_open_intent(&nd);
		return ERR_PTR(error);
	}
	nd->flags &= ~LOOKUP_PARENT;
	if (nd->last_type == LAST_BIND)
	nd.flags &= ~LOOKUP_PARENT;
	if (nd.last_type == LAST_BIND)
		goto ok;
	error = -EISDIR;
	if (nd->last_type != LAST_NORM)
	if (nd.last_type != LAST_NORM)
		goto exit;
	if (nd->last.name[nd->last.len]) {
		__putname(nd->last.name);
	if (nd.last.name[nd.last.len]) {
		__putname(nd.last.name);
		goto exit;
	}
	error = -ELOOP;
	if (count++==32) {
		__putname(nd->last.name);
		__putname(nd.last.name);
		goto exit;
	}
	dir = nd->path.dentry;
	dir = nd.path.dentry;
	mutex_lock(&dir->d_inode->i_mutex);
	path.dentry = lookup_hash(nd);
	path.mnt = nd->path.mnt;
	__putname(nd->last.name);
	path.dentry = lookup_hash(&nd);
	path.mnt = nd.path.mnt;
	__putname(nd.last.name);
	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
 * @nd: nameidata info
+0 −19
Original line number Diff line number Diff line
@@ -796,25 +796,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
	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
 * @nd: pointer to nameidata
+2 −1
Original line number Diff line number Diff line
@@ -1735,7 +1735,8 @@ extern struct file *create_read_pipe(struct file *f);
extern struct file *create_write_pipe(void);
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 kernel_read(struct file *, unsigned long, char *, unsigned long);