aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/internal.h5
-rw-r--r--fs/namei.c95
-rw-r--r--fs/open.c87
-rw-r--r--include/linux/namei.h14
4 files changed, 48 insertions, 153 deletions
diff --git a/fs/internal.h b/fs/internal.h
index 70067775df2e..ae69a3b150d7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -82,13 +82,10 @@ extern struct super_block *user_get_super(dev_t);
82/* 82/*
83 * open.c 83 * open.c
84 */ 84 */
85struct nameidata;
86extern struct file *nameidata_to_filp(struct nameidata *);
87extern void release_open_intent(struct nameidata *);
88struct opendata { 85struct opendata {
89 struct dentry *dentry; 86 struct dentry *dentry;
90 struct vfsmount *mnt; 87 struct vfsmount *mnt;
91 struct file **filp; 88 struct file *filp;
92}; 89};
93struct open_flags { 90struct open_flags {
94 int open_flag; 91 int open_flag;
diff --git a/fs/namei.c b/fs/namei.c
index 9e11ae83bff6..0ed876259f8b 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -463,22 +463,6 @@ err_root:
463 return -ECHILD; 463 return -ECHILD;
464} 464}
465 465
466/**
467 * release_open_intent - free up open intent resources
468 * @nd: pointer to nameidata
469 */
470void release_open_intent(struct nameidata *nd)
471{
472 struct file *file = nd->intent.open.file;
473
474 if (file && !IS_ERR(file)) {
475 if (file->f_path.dentry == NULL)
476 put_filp(file);
477 else
478 fput(file);
479 }
480}
481
482static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) 466static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
483{ 467{
484 return dentry->d_op->d_revalidate(dentry, nd); 468 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)
2210} 2194}
2211 2195
2212static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, 2196static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
2213 struct path *path, const struct open_flags *op, 2197 struct path *path, struct opendata *od,
2198 const struct open_flags *op,
2214 int *want_write, bool need_lookup, 2199 int *want_write, bool need_lookup,
2215 bool *created) 2200 bool *created)
2216{ 2201{
@@ -2219,7 +2204,6 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
2219 umode_t mode; 2204 umode_t mode;
2220 int error; 2205 int error;
2221 int acc_mode; 2206 int acc_mode;
2222 struct opendata od;
2223 struct file *filp; 2207 struct file *filp;
2224 int create_error = 0; 2208 int create_error = 0;
2225 struct dentry *const DENTRY_NOT_SET = (void *) -1UL; 2209 struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
@@ -2285,14 +2269,13 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
2285 if (nd->flags & LOOKUP_DIRECTORY) 2269 if (nd->flags & LOOKUP_DIRECTORY)
2286 open_flag |= O_DIRECTORY; 2270 open_flag |= O_DIRECTORY;
2287 2271
2288 od.dentry = DENTRY_NOT_SET; 2272 od->dentry = DENTRY_NOT_SET;
2289 od.mnt = nd->path.mnt; 2273 od->mnt = nd->path.mnt;
2290 od.filp = &nd->intent.open.file; 2274 filp = dir->i_op->atomic_open(dir, dentry, od, open_flag, mode,
2291 filp = dir->i_op->atomic_open(dir, dentry, &od, open_flag, mode,
2292 created); 2275 created);
2293 if (IS_ERR(filp)) { 2276 if (IS_ERR(filp)) {
2294 if (WARN_ON(od.dentry != DENTRY_NOT_SET)) 2277 if (WARN_ON(od->dentry != DENTRY_NOT_SET))
2295 dput(od.dentry); 2278 dput(od->dentry);
2296 2279
2297 if (create_error && PTR_ERR(filp) == -ENOENT) 2280 if (create_error && PTR_ERR(filp) == -ENOENT)
2298 filp = ERR_PTR(create_error); 2281 filp = ERR_PTR(create_error);
@@ -2306,13 +2289,13 @@ static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry,
2306 } 2289 }
2307 2290
2308 if (!filp) { 2291 if (!filp) {
2309 if (WARN_ON(od.dentry == DENTRY_NOT_SET)) { 2292 if (WARN_ON(od->dentry == DENTRY_NOT_SET)) {
2310 filp = ERR_PTR(-EIO); 2293 filp = ERR_PTR(-EIO);
2311 goto out; 2294 goto out;
2312 } 2295 }
2313 if (od.dentry) { 2296 if (od->dentry) {
2314 dput(dentry); 2297 dput(dentry);
2315 dentry = od.dentry; 2298 dentry = od->dentry;
2316 } 2299 }
2317 goto looked_up; 2300 goto looked_up;
2318 } 2301 }
@@ -2375,6 +2358,7 @@ looked_up:
2375 * was performed, only lookup. 2358 * was performed, only lookup.
2376 */ 2359 */
2377static struct file *lookup_open(struct nameidata *nd, struct path *path, 2360static struct file *lookup_open(struct nameidata *nd, struct path *path,
2361 struct opendata *od,
2378 const struct open_flags *op, 2362 const struct open_flags *op,
2379 int *want_write, bool *created) 2363 int *want_write, bool *created)
2380{ 2364{
@@ -2394,7 +2378,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
2394 goto out_no_open; 2378 goto out_no_open;
2395 2379
2396 if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) { 2380 if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
2397 return atomic_open(nd, dentry, path, op, want_write, 2381 return atomic_open(nd, dentry, path, od, op, want_write,
2398 need_lookup, created); 2382 need_lookup, created);
2399 } 2383 }
2400 2384
@@ -2416,7 +2400,7 @@ static struct file *lookup_open(struct nameidata *nd, struct path *path,
2416 * rw->ro transition does not occur between 2400 * rw->ro transition does not occur between
2417 * the time when the file is created and when 2401 * the time when the file is created and when
2418 * a permanent write count is taken through 2402 * a permanent write count is taken through
2419 * the 'struct file' in nameidata_to_filp(). 2403 * the 'struct file' in finish_open().
2420 */ 2404 */
2421 error = mnt_want_write(nd->path.mnt); 2405 error = mnt_want_write(nd->path.mnt);
2422 if (error) 2406 if (error)
@@ -2444,7 +2428,8 @@ out_dput:
2444 * Handle the last step of open() 2428 * Handle the last step of open()
2445 */ 2429 */
2446static struct file *do_last(struct nameidata *nd, struct path *path, 2430static struct file *do_last(struct nameidata *nd, struct path *path,
2447 const struct open_flags *op, const char *pathname) 2431 struct opendata *od, const struct open_flags *op,
2432 const char *pathname)
2448{ 2433{
2449 struct dentry *dir = nd->path.dentry; 2434 struct dentry *dir = nd->path.dentry;
2450 int open_flag = op->open_flag; 2435 int open_flag = op->open_flag;
@@ -2521,7 +2506,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
2521 2506
2522retry_lookup: 2507retry_lookup:
2523 mutex_lock(&dir->d_inode->i_mutex); 2508 mutex_lock(&dir->d_inode->i_mutex);
2524 filp = lookup_open(nd, path, op, &want_write, &created); 2509 filp = lookup_open(nd, path, od, op, &want_write, &created);
2525 mutex_unlock(&dir->d_inode->i_mutex); 2510 mutex_unlock(&dir->d_inode->i_mutex);
2526 2511
2527 if (filp) { 2512 if (filp) {
@@ -2627,7 +2612,8 @@ common:
2627 error = may_open(&nd->path, acc_mode, open_flag); 2612 error = may_open(&nd->path, acc_mode, open_flag);
2628 if (error) 2613 if (error)
2629 goto exit; 2614 goto exit;
2630 filp = nameidata_to_filp(nd); 2615 od->mnt = nd->path.mnt;
2616 filp = finish_open(od, nd->path.dentry, NULL);
2631 if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) { 2617 if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
2632 BUG_ON(save_parent.dentry != dir); 2618 BUG_ON(save_parent.dentry != dir);
2633 path_put(&nd->path); 2619 path_put(&nd->path);
@@ -2642,6 +2628,11 @@ common:
2642 retried = true; 2628 retried = true;
2643 goto retry_lookup; 2629 goto retry_lookup;
2644 } 2630 }
2631 if (IS_ERR(filp))
2632 goto out;
2633 error = open_check_o_direct(filp);
2634 if (error)
2635 goto exit_fput;
2645opened: 2636opened:
2646 if (!IS_ERR(filp)) { 2637 if (!IS_ERR(filp)) {
2647 error = ima_file_check(filp, op->acc_mode); 2638 error = ima_file_check(filp, op->acc_mode);
@@ -2671,24 +2662,26 @@ exit_dput:
2671exit: 2662exit:
2672 filp = ERR_PTR(error); 2663 filp = ERR_PTR(error);
2673 goto out; 2664 goto out;
2665exit_fput:
2666 fput(filp);
2667 goto exit;
2668
2674} 2669}
2675 2670
2676static struct file *path_openat(int dfd, const char *pathname, 2671static struct file *path_openat(int dfd, const char *pathname,
2677 struct nameidata *nd, const struct open_flags *op, int flags) 2672 struct nameidata *nd, const struct open_flags *op, int flags)
2678{ 2673{
2679 struct file *base = NULL; 2674 struct file *base = NULL;
2680 struct file *filp; 2675 struct opendata od;
2676 struct file *res;
2681 struct path path; 2677 struct path path;
2682 int error; 2678 int error;
2683 2679
2684 filp = get_empty_filp(); 2680 od.filp = get_empty_filp();
2685 if (!filp) 2681 if (!od.filp)
2686 return ERR_PTR(-ENFILE); 2682 return ERR_PTR(-ENFILE);
2687 2683
2688 filp->f_flags = op->open_flag; 2684 od.filp->f_flags = op->open_flag;
2689 nd->intent.open.file = filp;
2690 nd->intent.open.flags = open_to_namei_flags(op->open_flag);
2691 nd->intent.open.create_mode = op->mode;
2692 2685
2693 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); 2686 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
2694 if (unlikely(error)) 2687 if (unlikely(error))
@@ -2699,14 +2692,14 @@ static struct file *path_openat(int dfd, const char *pathname,
2699 if (unlikely(error)) 2692 if (unlikely(error))
2700 goto out_filp; 2693 goto out_filp;
2701 2694
2702 filp = do_last(nd, &path, op, pathname); 2695 res = do_last(nd, &path, &od, op, pathname);
2703 while (unlikely(!filp)) { /* trailing symlink */ 2696 while (unlikely(!res)) { /* trailing symlink */
2704 struct path link = path; 2697 struct path link = path;
2705 void *cookie; 2698 void *cookie;
2706 if (!(nd->flags & LOOKUP_FOLLOW)) { 2699 if (!(nd->flags & LOOKUP_FOLLOW)) {
2707 path_put_conditional(&path, nd); 2700 path_put_conditional(&path, nd);
2708 path_put(&nd->path); 2701 path_put(&nd->path);
2709 filp = ERR_PTR(-ELOOP); 2702 res = ERR_PTR(-ELOOP);
2710 break; 2703 break;
2711 } 2704 }
2712 nd->flags |= LOOKUP_PARENT; 2705 nd->flags |= LOOKUP_PARENT;
@@ -2714,7 +2707,7 @@ static struct file *path_openat(int dfd, const char *pathname,
2714 error = follow_link(&link, nd, &cookie); 2707 error = follow_link(&link, nd, &cookie);
2715 if (unlikely(error)) 2708 if (unlikely(error))
2716 goto out_filp; 2709 goto out_filp;
2717 filp = do_last(nd, &path, op, pathname); 2710 res = do_last(nd, &path, &od, op, pathname);
2718 put_link(nd, &link, cookie); 2711 put_link(nd, &link, cookie);
2719 } 2712 }
2720out: 2713out:
@@ -2722,17 +2715,20 @@ out:
2722 path_put(&nd->root); 2715 path_put(&nd->root);
2723 if (base) 2716 if (base)
2724 fput(base); 2717 fput(base);
2725 release_open_intent(nd); 2718 if (od.filp) {
2726 if (filp == ERR_PTR(-EOPENSTALE)) { 2719 BUG_ON(od.filp->f_path.dentry);
2720 put_filp(od.filp);
2721 }
2722 if (res == ERR_PTR(-EOPENSTALE)) {
2727 if (flags & LOOKUP_RCU) 2723 if (flags & LOOKUP_RCU)
2728 filp = ERR_PTR(-ECHILD); 2724 res = ERR_PTR(-ECHILD);
2729 else 2725 else
2730 filp = ERR_PTR(-ESTALE); 2726 res = ERR_PTR(-ESTALE);
2731 } 2727 }
2732 return filp; 2728 return res;
2733 2729
2734out_filp: 2730out_filp:
2735 filp = ERR_PTR(error); 2731 res = ERR_PTR(error);
2736 goto out; 2732 goto out;
2737} 2733}
2738 2734
@@ -2788,7 +2784,6 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
2788 goto out; 2784 goto out;
2789 nd.flags &= ~LOOKUP_PARENT; 2785 nd.flags &= ~LOOKUP_PARENT;
2790 nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL; 2786 nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
2791 nd.intent.open.flags = O_EXCL;
2792 2787
2793 /* 2788 /*
2794 * Do the final lookup. 2789 * Do the final lookup.
diff --git a/fs/open.c b/fs/open.c
index 13bece4f36a4..937f4ec20180 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -771,46 +771,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
771} 771}
772 772
773/** 773/**
774 * lookup_instantiate_filp - instantiates the open intent filp
775 * @nd: pointer to nameidata
776 * @dentry: pointer to dentry
777 * @open: open callback
778 *
779 * Helper for filesystems that want to use lookup open intents and pass back
780 * a fully instantiated struct file to the caller.
781 * This function is meant to be called from within a filesystem's
782 * lookup method.
783 * Beware of calling it for non-regular files! Those ->open methods might block
784 * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
785 * leading to a deadlock, as nobody can open that fifo anymore, because
786 * another process to open fifo will block on locked parent when doing lookup).
787 * Note that in case of error, nd->intent.open.file is destroyed, but the
788 * path information remains valid.
789 * If the open callback is set to NULL, then the standard f_op->open()
790 * filesystem callback is substituted.
791 */
792struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
793 int (*open)(struct inode *, struct file *))
794{
795 const struct cred *cred = current_cred();
796
797 if (IS_ERR(nd->intent.open.file))
798 goto out;
799 if (IS_ERR(dentry))
800 goto out_err;
801 nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
802 nd->intent.open.file,
803 open, cred);
804out:
805 return nd->intent.open.file;
806out_err:
807 release_open_intent(nd);
808 nd->intent.open.file = ERR_CAST(dentry);
809 goto out;
810}
811EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
812
813/**
814 * finish_open - finish opening a file 774 * finish_open - finish opening a file
815 * @od: opaque open data 775 * @od: opaque open data
816 * @dentry: pointer to dentry 776 * @dentry: pointer to dentry
@@ -829,9 +789,9 @@ struct file *finish_open(struct opendata *od, struct dentry *dentry,
829 mntget(od->mnt); 789 mntget(od->mnt);
830 dget(dentry); 790 dget(dentry);
831 791
832 res = do_dentry_open(dentry, od->mnt, *od->filp, open, current_cred()); 792 res = do_dentry_open(dentry, od->mnt, od->filp, open, current_cred());
833 if (!IS_ERR(res)) 793 if (!IS_ERR(res))
834 *od->filp = NULL; 794 od->filp = NULL;
835 795
836 return res; 796 return res;
837} 797}
@@ -852,49 +812,6 @@ void finish_no_open(struct opendata *od, struct dentry *dentry)
852} 812}
853EXPORT_SYMBOL(finish_no_open); 813EXPORT_SYMBOL(finish_no_open);
854 814
855/**
856 * nameidata_to_filp - convert a nameidata to an open filp.
857 * @nd: pointer to nameidata
858 * @flags: open flags
859 *
860 * Note that this function destroys the original nameidata
861 */
862struct file *nameidata_to_filp(struct nameidata *nd)
863{
864 const struct cred *cred = current_cred();
865 struct file *filp;
866
867 /* Pick up the filp from the open intent */
868 filp = nd->intent.open.file;
869
870 /* Has the filesystem initialised the file for us? */
871 if (filp->f_path.dentry != NULL) {
872 nd->intent.open.file = NULL;
873 } else {
874 struct file *res;
875
876 path_get(&nd->path);
877 res = do_dentry_open(nd->path.dentry, nd->path.mnt,
878 filp, NULL, cred);
879 if (!IS_ERR(res)) {
880 int error;
881
882 nd->intent.open.file = NULL;
883 BUG_ON(res != filp);
884
885 error = open_check_o_direct(filp);
886 if (error) {
887 fput(filp);
888 filp = ERR_PTR(error);
889 }
890 } else {
891 /* Allow nd->intent.open.file to be recycled */
892 filp = res;
893 }
894 }
895 return filp;
896}
897
898/* 815/*
899 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an 816 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
900 * error. 817 * error.
diff --git a/include/linux/namei.h b/include/linux/namei.h
index ffc02135c483..23d859879210 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -7,12 +7,6 @@
7 7
8struct vfsmount; 8struct vfsmount;
9 9
10struct open_intent {
11 int flags;
12 int create_mode;
13 struct file *file;
14};
15
16enum { MAX_NESTED_LINKS = 8 }; 10enum { MAX_NESTED_LINKS = 8 };
17 11
18struct nameidata { 12struct nameidata {
@@ -25,11 +19,6 @@ struct nameidata {
25 int last_type; 19 int last_type;
26 unsigned depth; 20 unsigned depth;
27 char *saved_names[MAX_NESTED_LINKS + 1]; 21 char *saved_names[MAX_NESTED_LINKS + 1];
28
29 /* Intent data */
30 union {
31 struct open_intent open;
32 } intent;
33}; 22};
34 23
35/* 24/*
@@ -82,9 +71,6 @@ extern int kern_path_parent(const char *, struct nameidata *);
82extern int vfs_path_lookup(struct dentry *, struct vfsmount *, 71extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
83 const char *, unsigned int, struct path *); 72 const char *, unsigned int, struct path *);
84 73
85extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
86 int (*open)(struct inode *, struct file *));
87
88extern struct dentry *lookup_one_len(const char *, struct dentry *, int); 74extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
89 75
90extern int follow_down_one(struct path *); 76extern int follow_down_one(struct path *);