From: Miklos Szeredi <mszeredi@xxxxxxx> 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: Miklos Szeredi <mszeredi@xxxxxxx> --- fs/internal.h | 5 +-- fs/namei.c | 114 ++++++++++++++++++++++--------------------------- fs/open.c | 97 +++++------------------------------------ include/linux/namei.h | 11 ----- 4 files changed, 64 insertions(+), 163 deletions(-) diff --git a/fs/internal.h b/fs/internal.h index 438fbd3..f99e89a 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -84,13 +84,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 f6dfd7c..66b26da 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -476,22 +476,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); @@ -2109,7 +2093,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) { struct inode *dir = nd->path.dentry->d_inode; @@ -2118,7 +2103,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, int error; bool created = false; int acc_mode; - struct opendata od; struct file *filp; int create_error = 0; struct dentry *const DENTRY_NOT_SET = (void *) -1UL; @@ -2184,14 +2168,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); @@ -2205,13 +2188,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; } @@ -2271,6 +2254,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) { struct dentry *dir = nd->path.dentry; @@ -2287,7 +2271,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); } @@ -2309,7 +2293,8 @@ out_no_open: * 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; struct dentry *dentry; @@ -2385,7 +2370,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path, mutex_lock(&dir->d_inode->i_mutex); - filp = lookup_open(nd, path, op, &want_write); + filp = lookup_open(nd, path, od, op, &want_write); if (filp) { mutex_unlock(&dir->d_inode->i_mutex); if (IS_ERR(filp)) @@ -2411,7 +2396,7 @@ static struct file *do_last(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(). */ if (!want_write) { error = mnt_want_write(nd->path.mnt); @@ -2505,23 +2490,22 @@ 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 (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); - if (error) { - fput(filp); - filp = ERR_PTR(error); - } - } - if (!IS_ERR(filp)) { - if (will_truncate) { - error = handle_truncate(filp); - if (error) { - fput(filp); - filp = ERR_PTR(error); - } - } + error = ima_file_check(filp, op->acc_mode); + if (error) + goto exit_fput; + + if (will_truncate) { + error = handle_truncate(filp); + if (error) + goto exit_fput; } out: if (want_write) @@ -2537,6 +2521,10 @@ exit: filp = ERR_PTR(error); goto out; +exit_fput: + fput(filp); + goto exit; + terminate: terminate_walk(nd); return ERR_PTR(error); @@ -2546,18 +2534,16 @@ 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)) @@ -2568,23 +2554,23 @@ 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; nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); error = follow_link(&link, nd, &cookie); if (unlikely(error)) - filp = ERR_PTR(error); + res = ERR_PTR(error); else - filp = do_last(nd, &path, op, pathname); + res = do_last(nd, &path, &od, op, pathname); put_link(nd, &link, cookie); } out: @@ -2592,11 +2578,14 @@ out: path_put(&nd->root); if (base) fput(base); - release_open_intent(nd); - return filp; + if (od.filp) { + BUG_ON(od.filp->f_path.dentry); + put_filp(od.filp); + } + return res; out_filp: - filp = ERR_PTR(error); + res = ERR_PTR(error); goto out; } @@ -2652,7 +2641,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 cd73de1..a18e6bc 100644 --- a/fs/open.c +++ b/fs/open.c @@ -743,62 +743,6 @@ cleanup_file: return ERR_PTR(error); } -static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, - struct file *f, - int (*open)(struct inode *, struct file *), - const struct cred *cred) -{ - struct file *res = do_dentry_open(dentry, mnt, f, open, cred); - if (!IS_ERR(res)) { - int error = open_check_o_direct(f); - if (error) { - fput(res); - res = ERR_PTR(error); - } - } - 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 @@ -815,8 +759,8 @@ struct file *finish_open(struct opendata *od, struct dentry *dentry, { struct file *filp; - filp = *(od->filp); - *(od->filp) = NULL; + filp = od->filp; + od->filp = NULL; mntget(od->mnt); dget(dentry); @@ -840,31 +784,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; - nd->intent.open.file = NULL; - - /* Has the filesystem initialised the file for us? */ - if (filp->f_path.dentry == NULL) { - path_get(&nd->path); - filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp, - NULL, cred); - } - return filp; -} - /* * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an * error. @@ -873,7 +792,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, const struct cred *cred) { int error; - struct file *f; + struct file *f, *res; validate_creds(cred); @@ -889,7 +808,15 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, } f->f_flags = flags; - return __dentry_open(dentry, mnt, f, NULL, cred); + res = do_dentry_open(dentry, mnt, f, NULL, cred); + if (!IS_ERR(res)) { + int error = open_check_o_direct(f); + if (error) { + fput(res); + res = ERR_PTR(error); + } + } + return res; } EXPORT_SYMBOL(dentry_open); diff --git a/include/linux/namei.h b/include/linux/namei.h index ffc0213..54dadda 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; }; /* -- 1.7.7 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html