diff options
| -rw-r--r-- | fs/internal.h | 5 | ||||
| -rw-r--r-- | fs/namei.c | 95 | ||||
| -rw-r--r-- | fs/open.c | 87 | ||||
| -rw-r--r-- | include/linux/namei.h | 14 | 
4 files changed, 48 insertions, 153 deletions
diff --git a/fs/internal.h b/fs/internal.h index 70067775df2..ae69a3b150d 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -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; diff --git a/fs/namei.c b/fs/namei.c index 9e11ae83bff..0ed876259f8 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -463,22 +463,6 @@ err_root:  	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 @@ looked_up:   * 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 @@ out_dput:   * 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 @@ common:  	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 @@ common:  		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 @@ exit_dput:  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 @@ out:  		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. diff --git a/fs/open.c b/fs/open.c index 13bece4f36a..937f4ec2018 100644 --- a/fs/open.c +++ b/fs/open.c @@ -771,46 +771,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,  }  /** - * 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   * @dentry: pointer to dentry @@ -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. diff --git a/include/linux/namei.h b/include/linux/namei.h index ffc02135c48..23d85987921 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -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 *);  |