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

Commit 015c3bbc authored by Miklos Szeredi's avatar Miklos Szeredi Committed by Al Viro
Browse files

vfs: remove open intents from nameidata



All users of open intents have been converted to use ->atomic_{open,create}.

This patch gets rid of nd->intent.open and related infrastructure.

Signed-off-by: default avatarMiklos Szeredi <mszeredi@suse.cz>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e43ae79c
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -82,13 +82,10 @@ extern struct super_block *user_get_super(dev_t);
/*
 * open.c
 */
struct nameidata;
extern struct file *nameidata_to_filp(struct nameidata *);
extern void release_open_intent(struct nameidata *);
struct opendata {
	struct dentry *dentry;
	struct vfsmount *mnt;
	struct file **filp;
	struct file *filp;
};
struct open_flags {
	int open_flag;
+45 −50
Original line number Diff line number Diff line
@@ -463,22 +463,6 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
	return -ECHILD;
}

/**
 * release_open_intent - free up open intent resources
 * @nd: pointer to nameidata
 */
void release_open_intent(struct nameidata *nd)
{
	struct file *file = nd->intent.open.file;

	if (file && !IS_ERR(file)) {
		if (file->f_path.dentry == NULL)
			put_filp(file);
		else
			fput(file);
	}
}

static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
	return dentry->d_op->d_revalidate(dentry, nd);
@@ -2210,7 +2194,8 @@ static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode)
}

static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
				struct path *path, const struct open_flags *op,
				struct path *path, struct opendata *od,
				const struct open_flags *op,
				int *want_write, bool need_lookup,
				bool *created)
{
@@ -2219,7 +2204,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	umode_t mode;
	int error;
	int acc_mode;
	struct opendata od;
	struct file *filp;
	int create_error = 0;
	struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
@@ -2285,14 +2269,13 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	if (nd->flags & LOOKUP_DIRECTORY)
		open_flag |= O_DIRECTORY;

	od.dentry = DENTRY_NOT_SET;
	od.mnt = nd->path.mnt;
	od.filp = &nd->intent.open.file;
	filp = dir->i_op->atomic_open(dir, dentry, &od, open_flag, mode,
	od->dentry = DENTRY_NOT_SET;
	od->mnt = nd->path.mnt;
	filp = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode,
				      created);
	if (IS_ERR(filp)) {
		if (WARN_ON(od.dentry != DENTRY_NOT_SET))
			dput(od.dentry);
		if (WARN_ON(od->dentry != DENTRY_NOT_SET))
			dput(od->dentry);

		if (create_error && PTR_ERR(filp) == -ENOENT)
			filp = ERR_PTR(create_error);
@@ -2306,13 +2289,13 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
	}

	if (!filp) {
		if (WARN_ON(od.dentry == DENTRY_NOT_SET)) {
		if (WARN_ON(od->dentry == DENTRY_NOT_SET)) {
			filp = ERR_PTR(-EIO);
			goto out;
		}
		if (od.dentry) {
		if (od->dentry) {
			dput(dentry);
			dentry = od.dentry;
			dentry = od->dentry;
		}
		goto looked_up;
	}
@@ -2375,6 +2358,7 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
 * was performed, only lookup.
 */
static struct file *lookup_open(struct nameidata *nd, struct path *path,
				struct opendata *od,
				const struct open_flags *op,
				int *want_write, bool *created)
{
@@ -2394,7 +2378,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
		goto out_no_open;

	if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
		return atomic_open(nd, dentry, path, op, want_write,
		return atomic_open(nd, dentry, path, od, op, want_write,
				   need_lookup, created);
	}

@@ -2416,7 +2400,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
		 * 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().
		 * the 'struct file' in finish_open().
		 */
		error = mnt_want_write(nd->path.mnt);
		if (error)
@@ -2444,7 +2428,8 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
 * Handle the last step of open()
 */
static struct file *do_last(struct nameidata *nd, struct path *path,
			    const struct open_flags *op, const char *pathname)
			    struct opendata *od, const struct open_flags *op,
			    const char *pathname)
{
	struct dentry *dir = nd->path.dentry;
	int open_flag = op->open_flag;
@@ -2521,7 +2506,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,

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

	if (filp) {
@@ -2627,7 +2612,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
	error = may_open(&nd->path, acc_mode, open_flag);
	if (error)
		goto exit;
	filp = nameidata_to_filp(nd);
	od->mnt = nd->path.mnt;
	filp = finish_open(od, nd->path.dentry, NULL);
	if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
		BUG_ON(save_parent.dentry != dir);
		path_put(&nd->path);
@@ -2642,6 +2628,11 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
		retried = true;
		goto retry_lookup;
	}
	if (IS_ERR(filp))
		goto out;
	error = open_check_o_direct(filp);
	if (error)
		goto exit_fput;
opened:
	if (!IS_ERR(filp)) {
		error = ima_file_check(filp, op->acc_mode);
@@ -2671,24 +2662,26 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
exit:
	filp = ERR_PTR(error);
	goto out;
exit_fput:
	fput(filp);
	goto exit;

}

static struct file *path_openat(int dfd, const char *pathname,
		struct nameidata *nd, const struct open_flags *op, int flags)
{
	struct file *base = NULL;
	struct file *filp;
	struct opendata od;
	struct file *res;
	struct path path;
	int error;

	filp = get_empty_filp();
	if (!filp)
	od.filp = get_empty_filp();
	if (!od.filp)
		return ERR_PTR(-ENFILE);

	filp->f_flags = op->open_flag;
	nd->intent.open.file = filp;
	nd->intent.open.flags = open_to_namei_flags(op->open_flag);
	nd->intent.open.create_mode = op->mode;
	od.filp->f_flags = op->open_flag;

	error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
	if (unlikely(error))
@@ -2699,14 +2692,14 @@ static struct file *path_openat(int dfd, const char *pathname,
	if (unlikely(error))
		goto out_filp;

	filp = do_last(nd, &path, op, pathname);
	while (unlikely(!filp)) { /* trailing symlink */
	res = do_last(nd, &path, &od, op, pathname);
	while (unlikely(!res)) { /* trailing symlink */
		struct path link = path;
		void *cookie;
		if (!(nd->flags & LOOKUP_FOLLOW)) {
			path_put_conditional(&path, nd);
			path_put(&nd->path);
			filp = ERR_PTR(-ELOOP);
			res = ERR_PTR(-ELOOP);
			break;
		}
		nd->flags |= LOOKUP_PARENT;
@@ -2714,7 +2707,7 @@ static struct file *path_openat(int dfd, const char *pathname,
		error = follow_link(&link, nd, &cookie);
		if (unlikely(error))
			goto out_filp;
		filp = do_last(nd, &path, op, pathname);
		res = do_last(nd, &path, &od, op, pathname);
		put_link(nd, &link, cookie);
	}
out:
@@ -2722,17 +2715,20 @@ static struct file *path_openat(int dfd, const char *pathname,
		path_put(&nd->root);
	if (base)
		fput(base);
	release_open_intent(nd);
	if (filp == ERR_PTR(-EOPENSTALE)) {
	if (od.filp) {
		BUG_ON(od.filp->f_path.dentry);
		put_filp(od.filp);
	}
	if (res == ERR_PTR(-EOPENSTALE)) {
		if (flags & LOOKUP_RCU)
			filp = ERR_PTR(-ECHILD);
			res = ERR_PTR(-ECHILD);
		else
			filp = ERR_PTR(-ESTALE);
			res = ERR_PTR(-ESTALE);
	}
	return filp;
	return res;

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

@@ -2788,7 +2784,6 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
		goto out;
	nd.flags &= ~LOOKUP_PARENT;
	nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
	nd.intent.open.flags = O_EXCL;

	/*
	 * Do the final lookup.
+2 −85
Original line number Diff line number Diff line
@@ -770,46 +770,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
	return res;
}

/**
 * lookup_instantiate_filp - instantiates the open intent filp
 * @nd: pointer to nameidata
 * @dentry: pointer to dentry
 * @open: open callback
 *
 * Helper for filesystems that want to use lookup open intents and pass back
 * a fully instantiated struct file to the caller.
 * This function is meant to be called from within a filesystem's
 * lookup method.
 * Beware of calling it for non-regular files! Those ->open methods might block
 * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
 * leading to a deadlock, as nobody can open that fifo anymore, because
 * another process to open fifo will block on locked parent when doing lookup).
 * Note that in case of error, nd->intent.open.file is destroyed, but the
 * path information remains valid.
 * If the open callback is set to NULL, then the standard f_op->open()
 * filesystem callback is substituted.
 */
struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
		int (*open)(struct inode *, struct file *))
{
	const struct cred *cred = current_cred();

	if (IS_ERR(nd->intent.open.file))
		goto out;
	if (IS_ERR(dentry))
		goto out_err;
	nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
					     nd->intent.open.file,
					     open, cred);
out:
	return nd->intent.open.file;
out_err:
	release_open_intent(nd);
	nd->intent.open.file = ERR_CAST(dentry);
	goto out;
}
EXPORT_SYMBOL_GPL(lookup_instantiate_filp);

/**
 * finish_open - finish opening a file
 * @od: opaque open data
@@ -829,9 +789,9 @@ struct file *finish_open(struct opendata *od, struct dentry *dentry,
	mntget(od->mnt);
	dget(dentry);

	res = do_dentry_open(dentry, od->mnt, *od->filp, open, current_cred());
	res = do_dentry_open(dentry, od->mnt, od->filp, open, current_cred());
	if (!IS_ERR(res))
		*od->filp = NULL;
		od->filp = NULL;

	return res;
}
@@ -852,49 +812,6 @@ void finish_no_open(struct opendata *od, struct dentry *dentry)
}
EXPORT_SYMBOL(finish_no_open);

/**
 * nameidata_to_filp - convert a nameidata to an open filp.
 * @nd: pointer to nameidata
 * @flags: open flags
 *
 * Note that this function destroys the original nameidata
 */
struct file *nameidata_to_filp(struct nameidata *nd)
{
	const struct cred *cred = current_cred();
	struct file *filp;

	/* Pick up the filp from the open intent */
	filp = nd->intent.open.file;

	/* Has the filesystem initialised the file for us? */
	if (filp->f_path.dentry != NULL) {
		nd->intent.open.file = NULL;
	} else {
		struct file *res;

		path_get(&nd->path);
		res = do_dentry_open(nd->path.dentry, nd->path.mnt,
				     filp, NULL, cred);
		if (!IS_ERR(res)) {
			int error;

			nd->intent.open.file = NULL;
			BUG_ON(res != filp);

			error = open_check_o_direct(filp);
			if (error) {
				fput(filp);
				filp = ERR_PTR(error);
			}
		} else {
			/* Allow nd->intent.open.file to be recycled */
			filp = res;
		}
	}
	return filp;
}

/*
 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
 * error.
+0 −14
Original line number Diff line number Diff line
@@ -7,12 +7,6 @@

struct vfsmount;

struct open_intent {
	int	flags;
	int	create_mode;
	struct file *file;
};

enum { MAX_NESTED_LINKS = 8 };

struct nameidata {
@@ -25,11 +19,6 @@ struct nameidata {
	int		last_type;
	unsigned	depth;
	char *saved_names[MAX_NESTED_LINKS + 1];

	/* Intent data */
	union {
		struct open_intent open;
	} intent;
};

/*
@@ -82,9 +71,6 @@ extern int kern_path_parent(const char *, struct nameidata *);
extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
			   const char *, unsigned int, struct path *);

extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
		int (*open)(struct inode *, struct file *));

extern struct dentry *lookup_one_len(const char *, struct dentry *, int);

extern int follow_down_one(struct path *);