aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c89
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
565static int __emul_lookup_dentry(const char *, struct nameidata *);
566
567/* SMP-safe */ 564/* SMP-safe */
568static __always_inline int 565static __always_inline void
569walk_init_root(const char *name, struct nameidata *nd) 566walk_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);
631out:
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 */
1084static 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
1119void 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;
1132set_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. */
1142static int do_path_lookup(int dfd, const char *name, 1066static 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);
1197out:
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);