Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2675a4eb authored by Al Viro's avatar Al Viro
Browse files

fs/namei.c: get do_last() and friends return int



Same conventions as for ->atomic_open().  Trimmed the
forest of labels a bit, while we are at it...

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 30d90494
Loading
Loading
Loading
Loading
+70 −80
Original line number Original line Diff line number Diff line
@@ -2193,7 +2193,7 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode)
	return security_inode_create(dir->dentry->d_inode, dentry, mode);
	return security_inode_create(dir->dentry->d_inode, dentry, mode);
}
}


static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
static int atomic_open(struct nameidata *nd, struct dentry *dentry,
			struct path *path, struct file *file,
			struct path *path, struct file *file,
			const struct open_flags *op,
			const struct open_flags *op,
			bool *want_write, bool need_lookup,
			bool *want_write, bool need_lookup,
@@ -2204,7 +2204,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	umode_t mode;
	umode_t mode;
	int error;
	int error;
	int acc_mode;
	int acc_mode;
	struct file *filp = NULL;
	int create_error = 0;
	int create_error = 0;
	struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
	struct dentry *const DENTRY_NOT_SET = (void *) -1UL;


@@ -2212,7 +2211,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,


	/* Don't create child dentry for a dead directory. */
	/* Don't create child dentry for a dead directory. */
	if (unlikely(IS_DEADDIR(dir))) {
	if (unlikely(IS_DEADDIR(dir))) {
		filp = ERR_PTR(-ENOENT);
		error = -ENOENT;
		goto out;
		goto out;
	}
	}


@@ -2276,7 +2275,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	if (error < 0) {
	if (error < 0) {
		if (create_error && error == -ENOENT)
		if (create_error && error == -ENOENT)
			error = create_error;
			error = create_error;
		filp = ERR_PTR(error);
		goto out;
		goto out;
	}
	}


@@ -2288,7 +2286,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,


	if (error) {	/* returned 1, that is */
	if (error) {	/* returned 1, that is */
		if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
		if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
			filp = ERR_PTR(-EIO);
			error = -EIO;
			goto out;
			goto out;
		}
		}
		if (file->f_path.dentry) {
		if (file->f_path.dentry) {
@@ -2302,27 +2300,24 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	 * We didn't have the inode before the open, so check open permission
	 * We didn't have the inode before the open, so check open permission
	 * here.
	 * here.
	 */
	 */
	filp = file;
	error = may_open(&file->f_path, acc_mode, open_flag);
	error = may_open(&filp->f_path, acc_mode, open_flag);
	if (error)
	if (error) {
		fput(file);
		fput(filp);
		filp = ERR_PTR(error);
	}


out:
out:
	dput(dentry);
	dput(dentry);
	return filp;
	return error;


no_open:
no_open:
	if (need_lookup) {
	if (need_lookup) {
		dentry = lookup_real(dir, dentry, nd);
		dentry = lookup_real(dir, dentry, nd);
		if (IS_ERR(dentry))
		if (IS_ERR(dentry))
			return ERR_CAST(dentry);
			return PTR_ERR(dentry);


		if (create_error) {
		if (create_error) {
			int open_flag = op->open_flag;
			int open_flag = op->open_flag;


			filp = ERR_PTR(create_error);
			error = create_error;
			if ((open_flag & O_EXCL)) {
			if ((open_flag & O_EXCL)) {
				if (!dentry->d_inode)
				if (!dentry->d_inode)
					goto out;
					goto out;
@@ -2338,7 +2333,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
looked_up:
looked_up:
	path->dentry = dentry;
	path->dentry = dentry;
	path->mnt = nd->path.mnt;
	path->mnt = nd->path.mnt;
	return NULL;
	return 1;
}
}


/*
/*
@@ -2349,7 +2344,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
 * Returns open file or NULL on success, error otherwise.  NULL means no open
 * Returns open file or NULL on success, error otherwise.  NULL means no open
 * was performed, only lookup.
 * was performed, only lookup.
 */
 */
static struct file *lookup_open(struct nameidata *nd, struct path *path,
static int lookup_open(struct nameidata *nd, struct path *path,
			struct file *file,
			struct file *file,
			const struct open_flags *op,
			const struct open_flags *op,
			bool *want_write, int *opened)
			bool *want_write, int *opened)
@@ -2363,7 +2358,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
	*opened &= ~FILE_CREATED;
	*opened &= ~FILE_CREATED;
	dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup);
	dentry = lookup_dcache(&nd->last, dir, nd, &need_lookup);
	if (IS_ERR(dentry))
	if (IS_ERR(dentry))
		return ERR_CAST(dentry);
		return PTR_ERR(dentry);


	/* Cached positive dentry: will open in f_op->open */
	/* Cached positive dentry: will open in f_op->open */
	if (!need_lookup && dentry->d_inode)
	if (!need_lookup && dentry->d_inode)
@@ -2379,7 +2374,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,


		dentry = lookup_real(dir_inode, dentry, nd);
		dentry = lookup_real(dir_inode, dentry, nd);
		if (IS_ERR(dentry))
		if (IS_ERR(dentry))
			return ERR_CAST(dentry);
			return PTR_ERR(dentry);
	}
	}


	/* Negative dentry, just create the file */
	/* Negative dentry, just create the file */
@@ -2409,17 +2404,17 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
out_no_open:
out_no_open:
	path->dentry = dentry;
	path->dentry = dentry;
	path->mnt = nd->path.mnt;
	path->mnt = nd->path.mnt;
	return NULL;
	return 1;


out_dput:
out_dput:
	dput(dentry);
	dput(dentry);
	return ERR_PTR(error);
	return error;
}
}


/*
/*
 * Handle the last step of open()
 * Handle the last step of open()
 */
 */
static struct file *do_last(struct nameidata *nd, struct path *path,
static int do_last(struct nameidata *nd, struct path *path,
		   struct file *file, const struct open_flags *op,
		   struct file *file, const struct open_flags *op,
		   int *opened, const char *pathname)
		   int *opened, const char *pathname)
{
{
@@ -2428,7 +2423,6 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	bool will_truncate = (open_flag & O_TRUNC) != 0;
	bool will_truncate = (open_flag & O_TRUNC) != 0;
	bool want_write = false;
	bool want_write = false;
	int acc_mode = op->acc_mode;
	int acc_mode = op->acc_mode;
	struct file *filp;
	struct inode *inode;
	struct inode *inode;
	bool symlink_ok = false;
	bool symlink_ok = false;
	struct path save_parent = { .dentry = NULL, .mnt = NULL };
	struct path save_parent = { .dentry = NULL, .mnt = NULL };
@@ -2443,22 +2437,22 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	case LAST_DOT:
	case LAST_DOT:
		error = handle_dots(nd, nd->last_type);
		error = handle_dots(nd, nd->last_type);
		if (error)
		if (error)
			return ERR_PTR(error);
			return error;
		/* fallthrough */
		/* fallthrough */
	case LAST_ROOT:
	case LAST_ROOT:
		error = complete_walk(nd);
		error = complete_walk(nd);
		if (error)
		if (error)
			return ERR_PTR(error);
			return error;
		audit_inode(pathname, nd->path.dentry);
		audit_inode(pathname, nd->path.dentry);
		if (open_flag & O_CREAT) {
		if (open_flag & O_CREAT) {
			error = -EISDIR;
			error = -EISDIR;
			goto exit;
			goto out;
		}
		}
		goto finish_open;
		goto finish_open;
	case LAST_BIND:
	case LAST_BIND:
		error = complete_walk(nd);
		error = complete_walk(nd);
		if (error)
		if (error)
			return ERR_PTR(error);
			return error;
		audit_inode(pathname, dir);
		audit_inode(pathname, dir);
		goto finish_open;
		goto finish_open;
	}
	}
@@ -2474,7 +2468,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
			goto finish_lookup;
			goto finish_lookup;


		if (error < 0)
		if (error < 0)
			goto exit;
			goto out;


		BUG_ON(nd->inode != dir->d_inode);
		BUG_ON(nd->inode != dir->d_inode);
	} else {
	} else {
@@ -2486,29 +2480,29 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
		 */
		 */
		error = complete_walk(nd);
		error = complete_walk(nd);
		if (error)
		if (error)
			return ERR_PTR(error);
			return error;


		audit_inode(pathname, dir);
		audit_inode(pathname, dir);
		error = -EISDIR;
		error = -EISDIR;
		/* trailing slashes? */
		/* trailing slashes? */
		if (nd->last.name[nd->last.len])
		if (nd->last.name[nd->last.len])
			goto exit;
			goto out;
	}
	}


retry_lookup:
retry_lookup:
	mutex_lock(&dir->d_inode->i_mutex);
	mutex_lock(&dir->d_inode->i_mutex);
	filp = lookup_open(nd, path, file, op, &want_write, opened);
	error = lookup_open(nd, path, file, op, &want_write, opened);
	mutex_unlock(&dir->d_inode->i_mutex);
	mutex_unlock(&dir->d_inode->i_mutex);


	if (filp) {
	if (error <= 0) {
		if (IS_ERR(filp))
		if (error)
			goto out;
			goto out;


		if ((*opened & FILE_CREATED) ||
		if ((*opened & FILE_CREATED) ||
		    !S_ISREG(filp->f_path.dentry->d_inode->i_mode))
		    !S_ISREG(file->f_path.dentry->d_inode->i_mode))
			will_truncate = false;
			will_truncate = false;


		audit_inode(pathname, filp->f_path.dentry);
		audit_inode(pathname, file->f_path.dentry);
		goto opened;
		goto opened;
	}
	}


@@ -2554,18 +2548,18 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	error = -ENOENT;
	error = -ENOENT;
	if (!inode) {
	if (!inode) {
		path_to_nameidata(path, nd);
		path_to_nameidata(path, nd);
		goto exit;
		goto out;
	}
	}


	if (should_follow_link(inode, !symlink_ok)) {
	if (should_follow_link(inode, !symlink_ok)) {
		if (nd->flags & LOOKUP_RCU) {
		if (nd->flags & LOOKUP_RCU) {
			if (unlikely(unlazy_walk(nd, path->dentry))) {
			if (unlikely(unlazy_walk(nd, path->dentry))) {
				error = -ECHILD;
				error = -ECHILD;
				goto exit;
				goto out;
			}
			}
		}
		}
		BUG_ON(inode != path->dentry->d_inode);
		BUG_ON(inode != path->dentry->d_inode);
		return NULL;
		return 1;
	}
	}


	if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
	if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
@@ -2581,14 +2575,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	error = complete_walk(nd);
	error = complete_walk(nd);
	if (error) {
	if (error) {
		path_put(&save_parent);
		path_put(&save_parent);
		return ERR_PTR(error);
		return error;
	}
	}
	error = -EISDIR;
	error = -EISDIR;
	if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
	if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
		goto exit;
		goto out;
	error = -ENOTDIR;
	error = -ENOTDIR;
	if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
	if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
		goto exit;
		goto out;
	audit_inode(pathname, nd->path.dentry);
	audit_inode(pathname, nd->path.dentry);
finish_open:
finish_open:
	if (!S_ISREG(nd->inode->i_mode))
	if (!S_ISREG(nd->inode->i_mode))
@@ -2597,32 +2591,30 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	if (will_truncate) {
	if (will_truncate) {
		error = mnt_want_write(nd->path.mnt);
		error = mnt_want_write(nd->path.mnt);
		if (error)
		if (error)
			goto exit;
			goto out;
		want_write = true;
		want_write = true;
	}
	}
finish_open_created:
finish_open_created:
	error = may_open(&nd->path, acc_mode, open_flag);
	error = may_open(&nd->path, acc_mode, open_flag);
	if (error)
	if (error)
		goto exit;
		goto out;
	file->f_path.mnt = nd->path.mnt;
	file->f_path.mnt = nd->path.mnt;
	error = finish_open(file, nd->path.dentry, NULL, opened);
	error = finish_open(file, nd->path.dentry, NULL, opened);
	if (error) {
	if (error) {
		filp = ERR_PTR(error);
		if (error == -EOPENSTALE)
		if (error == -EOPENSTALE)
			goto stale_open;
			goto stale_open;
		goto out;
		goto out;
	}
	}
	filp = file;
opened:
opened:
	error = open_check_o_direct(filp);
	error = open_check_o_direct(file);
	if (error)
	if (error)
		goto exit_fput;
		goto exit_fput;
	error = ima_file_check(filp, op->acc_mode);
	error = ima_file_check(file, op->acc_mode);
	if (error)
	if (error)
		goto exit_fput;
		goto exit_fput;


	if (will_truncate) {
	if (will_truncate) {
		error = handle_truncate(filp);
		error = handle_truncate(file);
		if (error)
		if (error)
			goto exit_fput;
			goto exit_fput;
	}
	}
@@ -2631,16 +2623,14 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
		mnt_drop_write(nd->path.mnt);
		mnt_drop_write(nd->path.mnt);
	path_put(&save_parent);
	path_put(&save_parent);
	terminate_walk(nd);
	terminate_walk(nd);
	return filp;
	return error;


exit_dput:
exit_dput:
	path_put_conditional(path, nd);
	path_put_conditional(path, nd);
exit:
	filp = ERR_PTR(error);
	goto out;
	goto out;
exit_fput:
exit_fput:
	fput(filp);
	fput(file);
	goto exit;
	goto out;


stale_open:
stale_open:
	/* If no saved parent or already retried then can't retry */
	/* If no saved parent or already retried then can't retry */
@@ -2666,7 +2656,6 @@ static struct file *path_openat(int dfd, const char *pathname,
{
{
	struct file *base = NULL;
	struct file *base = NULL;
	struct file *file;
	struct file *file;
	struct file *res;
	struct path path;
	struct path path;
	int opened = 0;
	int opened = 0;
	int error;
	int error;
@@ -2679,29 +2668,29 @@ static struct file *path_openat(int dfd, const char *pathname,


	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
	if (unlikely(error))
	if (unlikely(error))
		goto out_filp;
		goto out;


	current->total_link_count = 0;
	current->total_link_count = 0;
	error = link_path_walk(pathname, nd);
	error = link_path_walk(pathname, nd);
	if (unlikely(error))
	if (unlikely(error))
		goto out_filp;
		goto out;


	res = do_last(nd, &path, file, op, &opened, pathname);
	error = do_last(nd, &path, file, op, &opened, pathname);
	while (unlikely(!res)) { /* trailing symlink */
	while (unlikely(error > 0)) { /* trailing symlink */
		struct path link = path;
		struct path link = path;
		void *cookie;
		void *cookie;
		if (!(nd->flags & LOOKUP_FOLLOW)) {
		if (!(nd->flags & LOOKUP_FOLLOW)) {
			path_put_conditional(&path, nd);
			path_put_conditional(&path, nd);
			path_put(&nd->path);
			path_put(&nd->path);
			res = ERR_PTR(-ELOOP);
			error = -ELOOP;
			break;
			break;
		}
		}
		nd->flags |= LOOKUP_PARENT;
		nd->flags |= LOOKUP_PARENT;
		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
		nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
		error = follow_link(&link, nd, &cookie);
		error = follow_link(&link, nd, &cookie);
		if (unlikely(error))
		if (unlikely(error))
			goto out_filp;
			break;
		res = do_last(nd, &path, file, op, &opened, pathname);
		error = do_last(nd, &path, file, op, &opened, pathname);
		put_link(nd, &link, cookie);
		put_link(nd, &link, cookie);
	}
	}
out:
out:
@@ -2709,19 +2698,20 @@ static struct file *path_openat(int dfd, const char *pathname,
		path_put(&nd->root);
		path_put(&nd->root);
	if (base)
	if (base)
		fput(base);
		fput(base);
	if (!(opened & FILE_OPENED))
	if (!(opened & FILE_OPENED)) {
		BUG_ON(!error);
		put_filp(file);
		put_filp(file);
	if (res == ERR_PTR(-EOPENSTALE)) {
	}
	if (unlikely(error)) {
		if (error == -EOPENSTALE) {
			if (flags & LOOKUP_RCU)
			if (flags & LOOKUP_RCU)
			res = ERR_PTR(-ECHILD);
				error = -ECHILD;
			else
			else
			res = ERR_PTR(-ESTALE);
				error = -ESTALE;
		}
		}
	return res;
		file = ERR_PTR(error);

	}
out_filp:
	return file;
	res = ERR_PTR(error);
	goto out;
}
}


struct file *do_filp_open(int dfd, const char *pathname,
struct file *do_filp_open(int dfd, const char *pathname,