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 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 | */ |
85 | struct nameidata; | ||
86 | extern struct file *nameidata_to_filp(struct nameidata *); | ||
87 | extern void release_open_intent(struct nameidata *); | ||
88 | struct opendata { | 85 | struct 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 | }; |
93 | struct open_flags { | 90 | struct 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 | */ | ||
470 | void 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 | |||
482 | static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) | 466 | static 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 | ||
2212 | static struct file *atomic_open(struct nameidata *nd, struct dentry *dentry, | 2196 | static 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 | */ |
2377 | static struct file *lookup_open(struct nameidata *nd, struct path *path, | 2360 | static 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 | */ |
2446 | static struct file *do_last(struct nameidata *nd, struct path *path, | 2430 | static 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 | ||
2522 | retry_lookup: | 2507 | retry_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; | ||
2645 | opened: | 2636 | opened: |
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: | |||
2671 | exit: | 2662 | exit: |
2672 | filp = ERR_PTR(error); | 2663 | filp = ERR_PTR(error); |
2673 | goto out; | 2664 | goto out; |
2665 | exit_fput: | ||
2666 | fput(filp); | ||
2667 | goto exit; | ||
2668 | |||
2674 | } | 2669 | } |
2675 | 2670 | ||
2676 | static struct file *path_openat(int dfd, const char *pathname, | 2671 | static 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 | } |
2720 | out: | 2713 | out: |
@@ -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 | ||
2734 | out_filp: | 2730 | out_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. |
@@ -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 | */ | ||
792 | struct 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); | ||
804 | out: | ||
805 | return nd->intent.open.file; | ||
806 | out_err: | ||
807 | release_open_intent(nd); | ||
808 | nd->intent.open.file = ERR_CAST(dentry); | ||
809 | goto out; | ||
810 | } | ||
811 | EXPORT_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 | } |
853 | EXPORT_SYMBOL(finish_no_open); | 813 | EXPORT_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 | */ | ||
862 | struct 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 | ||
8 | struct vfsmount; | 8 | struct vfsmount; |
9 | 9 | ||
10 | struct open_intent { | ||
11 | int flags; | ||
12 | int create_mode; | ||
13 | struct file *file; | ||
14 | }; | ||
15 | |||
16 | enum { MAX_NESTED_LINKS = 8 }; | 10 | enum { MAX_NESTED_LINKS = 8 }; |
17 | 11 | ||
18 | struct nameidata { | 12 | struct 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 *); | |||
82 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | 71 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
83 | const char *, unsigned int, struct path *); | 72 | const char *, unsigned int, struct path *); |
84 | 73 | ||
85 | extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | ||
86 | int (*open)(struct inode *, struct file *)); | ||
87 | |||
88 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); | 74 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); |
89 | 75 | ||
90 | extern int follow_down_one(struct path *); | 76 | extern int follow_down_one(struct path *); |