diff options
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 89 |
1 files changed, 2 insertions, 87 deletions
diff --git a/fs/namei.c b/fs/namei.c index 6c76e1ee9c45..095818089ac1 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/file.h> | 31 | #include <linux/file.h> |
32 | #include <linux/fcntl.h> | 32 | #include <linux/fcntl.h> |
33 | #include <linux/device_cgroup.h> | 33 | #include <linux/device_cgroup.h> |
34 | #include <asm/namei.h> | ||
35 | #include <asm/uaccess.h> | 34 | #include <asm/uaccess.h> |
36 | 35 | ||
37 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) | 36 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) |
@@ -562,27 +561,16 @@ out_unlock: | |||
562 | return result; | 561 | return result; |
563 | } | 562 | } |
564 | 563 | ||
565 | static int __emul_lookup_dentry(const char *, struct nameidata *); | ||
566 | |||
567 | /* SMP-safe */ | 564 | /* SMP-safe */ |
568 | static __always_inline int | 565 | static __always_inline void |
569 | walk_init_root(const char *name, struct nameidata *nd) | 566 | walk_init_root(const char *name, struct nameidata *nd) |
570 | { | 567 | { |
571 | struct fs_struct *fs = current->fs; | 568 | struct fs_struct *fs = current->fs; |
572 | 569 | ||
573 | read_lock(&fs->lock); | 570 | read_lock(&fs->lock); |
574 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { | ||
575 | nd->path = fs->altroot; | ||
576 | path_get(&fs->altroot); | ||
577 | read_unlock(&fs->lock); | ||
578 | if (__emul_lookup_dentry(name,nd)) | ||
579 | return 0; | ||
580 | read_lock(&fs->lock); | ||
581 | } | ||
582 | nd->path = fs->root; | 571 | nd->path = fs->root; |
583 | path_get(&fs->root); | 572 | path_get(&fs->root); |
584 | read_unlock(&fs->lock); | 573 | read_unlock(&fs->lock); |
585 | return 1; | ||
586 | } | 574 | } |
587 | 575 | ||
588 | /* | 576 | /* |
@@ -623,12 +611,9 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l | |||
623 | 611 | ||
624 | if (*link == '/') { | 612 | if (*link == '/') { |
625 | path_put(&nd->path); | 613 | path_put(&nd->path); |
626 | if (!walk_init_root(link, nd)) | 614 | walk_init_root(link, nd); |
627 | /* weird __emul_prefix() stuff did it */ | ||
628 | goto out; | ||
629 | } | 615 | } |
630 | res = link_path_walk(link, nd); | 616 | res = link_path_walk(link, nd); |
631 | out: | ||
632 | if (nd->depth || res || nd->last_type!=LAST_NORM) | 617 | if (nd->depth || res || nd->last_type!=LAST_NORM) |
633 | return res; | 618 | return res; |
634 | /* | 619 | /* |
@@ -1077,67 +1062,6 @@ static int path_walk(const char *name, struct nameidata *nd) | |||
1077 | return link_path_walk(name, nd); | 1062 | return link_path_walk(name, nd); |
1078 | } | 1063 | } |
1079 | 1064 | ||
1080 | /* | ||
1081 | * SMP-safe: Returns 1 and nd will have valid dentry and mnt, if | ||
1082 | * everything is done. Returns 0 and drops input nd, if lookup failed; | ||
1083 | */ | ||
1084 | static int __emul_lookup_dentry(const char *name, struct nameidata *nd) | ||
1085 | { | ||
1086 | if (path_walk(name, nd)) | ||
1087 | return 0; /* something went wrong... */ | ||
1088 | |||
1089 | if (!nd->path.dentry->d_inode || | ||
1090 | S_ISDIR(nd->path.dentry->d_inode->i_mode)) { | ||
1091 | struct path old_path = nd->path; | ||
1092 | struct qstr last = nd->last; | ||
1093 | int last_type = nd->last_type; | ||
1094 | struct fs_struct *fs = current->fs; | ||
1095 | |||
1096 | /* | ||
1097 | * NAME was not found in alternate root or it's a directory. | ||
1098 | * Try to find it in the normal root: | ||
1099 | */ | ||
1100 | nd->last_type = LAST_ROOT; | ||
1101 | read_lock(&fs->lock); | ||
1102 | nd->path = fs->root; | ||
1103 | path_get(&fs->root); | ||
1104 | read_unlock(&fs->lock); | ||
1105 | if (path_walk(name, nd) == 0) { | ||
1106 | if (nd->path.dentry->d_inode) { | ||
1107 | path_put(&old_path); | ||
1108 | return 1; | ||
1109 | } | ||
1110 | path_put(&nd->path); | ||
1111 | } | ||
1112 | nd->path = old_path; | ||
1113 | nd->last = last; | ||
1114 | nd->last_type = last_type; | ||
1115 | } | ||
1116 | return 1; | ||
1117 | } | ||
1118 | |||
1119 | void set_fs_altroot(void) | ||
1120 | { | ||
1121 | char *emul = __emul_prefix(); | ||
1122 | struct nameidata nd; | ||
1123 | struct path path = {}, old_path; | ||
1124 | int err; | ||
1125 | struct fs_struct *fs = current->fs; | ||
1126 | |||
1127 | if (!emul) | ||
1128 | goto set_it; | ||
1129 | err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd); | ||
1130 | if (!err) | ||
1131 | path = nd.path; | ||
1132 | set_it: | ||
1133 | write_lock(&fs->lock); | ||
1134 | old_path = fs->altroot; | ||
1135 | fs->altroot = path; | ||
1136 | write_unlock(&fs->lock); | ||
1137 | if (old_path.dentry) | ||
1138 | path_put(&old_path); | ||
1139 | } | ||
1140 | |||
1141 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ | 1065 | /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */ |
1142 | static int do_path_lookup(int dfd, const char *name, | 1066 | static int do_path_lookup(int dfd, const char *name, |
1143 | unsigned int flags, struct nameidata *nd) | 1067 | unsigned int flags, struct nameidata *nd) |
@@ -1153,14 +1077,6 @@ static int do_path_lookup(int dfd, const char *name, | |||
1153 | 1077 | ||
1154 | if (*name=='/') { | 1078 | if (*name=='/') { |
1155 | read_lock(&fs->lock); | 1079 | read_lock(&fs->lock); |
1156 | if (fs->altroot.dentry && !(nd->flags & LOOKUP_NOALT)) { | ||
1157 | nd->path = fs->altroot; | ||
1158 | path_get(&fs->altroot); | ||
1159 | read_unlock(&fs->lock); | ||
1160 | if (__emul_lookup_dentry(name,nd)) | ||
1161 | goto out; /* found in altroot */ | ||
1162 | read_lock(&fs->lock); | ||
1163 | } | ||
1164 | nd->path = fs->root; | 1080 | nd->path = fs->root; |
1165 | path_get(&fs->root); | 1081 | path_get(&fs->root); |
1166 | read_unlock(&fs->lock); | 1082 | read_unlock(&fs->lock); |
@@ -1194,7 +1110,6 @@ static int do_path_lookup(int dfd, const char *name, | |||
1194 | } | 1110 | } |
1195 | 1111 | ||
1196 | retval = path_walk(name, nd); | 1112 | retval = path_walk(name, nd); |
1197 | out: | ||
1198 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && | 1113 | if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry && |
1199 | nd->path.dentry->d_inode)) | 1114 | nd->path.dentry->d_inode)) |
1200 | audit_inode(name, nd->path.dentry); | 1115 | audit_inode(name, nd->path.dentry); |