aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c8
-rw-r--r--fs/namei.c52
2 files changed, 38 insertions, 22 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 4023e77b800e..7a5b51440afa 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2655,6 +2655,12 @@ static void __d_materialise_dentry(struct dentry *dentry, struct dentry *anon)
2655 dentry->d_parent = dentry; 2655 dentry->d_parent = dentry;
2656 list_del_init(&dentry->d_u.d_child); 2656 list_del_init(&dentry->d_u.d_child);
2657 anon->d_parent = dparent; 2657 anon->d_parent = dparent;
2658 if (likely(!d_unhashed(anon))) {
2659 hlist_bl_lock(&anon->d_sb->s_anon);
2660 __hlist_bl_del(&anon->d_hash);
2661 anon->d_hash.pprev = NULL;
2662 hlist_bl_unlock(&anon->d_sb->s_anon);
2663 }
2658 list_move(&anon->d_u.d_child, &dparent->d_subdirs); 2664 list_move(&anon->d_u.d_child, &dparent->d_subdirs);
2659 2665
2660 write_seqcount_end(&dentry->d_seq); 2666 write_seqcount_end(&dentry->d_seq);
@@ -2713,7 +2719,6 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
2713 write_seqlock(&rename_lock); 2719 write_seqlock(&rename_lock);
2714 __d_materialise_dentry(dentry, new); 2720 __d_materialise_dentry(dentry, new);
2715 write_sequnlock(&rename_lock); 2721 write_sequnlock(&rename_lock);
2716 __d_drop(new);
2717 _d_rehash(new); 2722 _d_rehash(new);
2718 spin_unlock(&new->d_lock); 2723 spin_unlock(&new->d_lock);
2719 spin_unlock(&inode->i_lock); 2724 spin_unlock(&inode->i_lock);
@@ -2777,7 +2782,6 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
2777 * could splice into our tree? */ 2782 * could splice into our tree? */
2778 __d_materialise_dentry(dentry, alias); 2783 __d_materialise_dentry(dentry, alias);
2779 write_sequnlock(&rename_lock); 2784 write_sequnlock(&rename_lock);
2780 __d_drop(alias);
2781 goto found; 2785 goto found;
2782 } else { 2786 } else {
2783 /* Nope, but we must(!) avoid directory 2787 /* Nope, but we must(!) avoid directory
diff --git a/fs/namei.c b/fs/namei.c
index 2be5120b81b3..215e44254c53 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -644,24 +644,22 @@ static int complete_walk(struct nameidata *nd)
644 644
645static __always_inline void set_root(struct nameidata *nd) 645static __always_inline void set_root(struct nameidata *nd)
646{ 646{
647 if (!nd->root.mnt) 647 get_fs_root(current->fs, &nd->root);
648 get_fs_root(current->fs, &nd->root);
649} 648}
650 649
651static int link_path_walk(const char *, struct nameidata *); 650static int link_path_walk(const char *, struct nameidata *);
652 651
653static __always_inline void set_root_rcu(struct nameidata *nd) 652static __always_inline unsigned set_root_rcu(struct nameidata *nd)
654{ 653{
655 if (!nd->root.mnt) { 654 struct fs_struct *fs = current->fs;
656 struct fs_struct *fs = current->fs; 655 unsigned seq, res;
657 unsigned seq;
658 656
659 do { 657 do {
660 seq = read_seqcount_begin(&fs->seq); 658 seq = read_seqcount_begin(&fs->seq);
661 nd->root = fs->root; 659 nd->root = fs->root;
662 nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq); 660 res = __read_seqcount_begin(&nd->root.dentry->d_seq);
663 } while (read_seqcount_retry(&fs->seq, seq)); 661 } while (read_seqcount_retry(&fs->seq, seq));
664 } 662 return res;
665} 663}
666 664
667static void path_put_conditional(struct path *path, struct nameidata *nd) 665static void path_put_conditional(struct path *path, struct nameidata *nd)
@@ -861,7 +859,8 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
861 return PTR_ERR(s); 859 return PTR_ERR(s);
862 } 860 }
863 if (*s == '/') { 861 if (*s == '/') {
864 set_root(nd); 862 if (!nd->root.mnt)
863 set_root(nd);
865 path_put(&nd->path); 864 path_put(&nd->path);
866 nd->path = nd->root; 865 nd->path = nd->root;
867 path_get(&nd->root); 866 path_get(&nd->root);
@@ -1138,13 +1137,15 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
1138 */ 1137 */
1139 *inode = path->dentry->d_inode; 1138 *inode = path->dentry->d_inode;
1140 } 1139 }
1141 return read_seqretry(&mount_lock, nd->m_seq) && 1140 return !read_seqretry(&mount_lock, nd->m_seq) &&
1142 !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT); 1141 !(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT);
1143} 1142}
1144 1143
1145static int follow_dotdot_rcu(struct nameidata *nd) 1144static int follow_dotdot_rcu(struct nameidata *nd)
1146{ 1145{
1147 set_root_rcu(nd); 1146 struct inode *inode = nd->inode;
1147 if (!nd->root.mnt)
1148 set_root_rcu(nd);
1148 1149
1149 while (1) { 1150 while (1) {
1150 if (nd->path.dentry == nd->root.dentry && 1151 if (nd->path.dentry == nd->root.dentry &&
@@ -1156,6 +1157,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1156 struct dentry *parent = old->d_parent; 1157 struct dentry *parent = old->d_parent;
1157 unsigned seq; 1158 unsigned seq;
1158 1159
1160 inode = parent->d_inode;
1159 seq = read_seqcount_begin(&parent->d_seq); 1161 seq = read_seqcount_begin(&parent->d_seq);
1160 if (read_seqcount_retry(&old->d_seq, nd->seq)) 1162 if (read_seqcount_retry(&old->d_seq, nd->seq))
1161 goto failed; 1163 goto failed;
@@ -1165,6 +1167,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1165 } 1167 }
1166 if (!follow_up_rcu(&nd->path)) 1168 if (!follow_up_rcu(&nd->path))
1167 break; 1169 break;
1170 inode = nd->path.dentry->d_inode;
1168 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1171 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1169 } 1172 }
1170 while (d_mountpoint(nd->path.dentry)) { 1173 while (d_mountpoint(nd->path.dentry)) {
@@ -1174,11 +1177,12 @@ static int follow_dotdot_rcu(struct nameidata *nd)
1174 break; 1177 break;
1175 nd->path.mnt = &mounted->mnt; 1178 nd->path.mnt = &mounted->mnt;
1176 nd->path.dentry = mounted->mnt.mnt_root; 1179 nd->path.dentry = mounted->mnt.mnt_root;
1180 inode = nd->path.dentry->d_inode;
1177 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq); 1181 nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
1178 if (!read_seqretry(&mount_lock, nd->m_seq)) 1182 if (read_seqretry(&mount_lock, nd->m_seq))
1179 goto failed; 1183 goto failed;
1180 } 1184 }
1181 nd->inode = nd->path.dentry->d_inode; 1185 nd->inode = inode;
1182 return 0; 1186 return 0;
1183 1187
1184failed: 1188failed:
@@ -1257,7 +1261,8 @@ static void follow_mount(struct path *path)
1257 1261
1258static void follow_dotdot(struct nameidata *nd) 1262static void follow_dotdot(struct nameidata *nd)
1259{ 1263{
1260 set_root(nd); 1264 if (!nd->root.mnt)
1265 set_root(nd);
1261 1266
1262 while(1) { 1267 while(1) {
1263 struct dentry *old = nd->path.dentry; 1268 struct dentry *old = nd->path.dentry;
@@ -1853,7 +1858,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1853 if (*name=='/') { 1858 if (*name=='/') {
1854 if (flags & LOOKUP_RCU) { 1859 if (flags & LOOKUP_RCU) {
1855 rcu_read_lock(); 1860 rcu_read_lock();
1856 set_root_rcu(nd); 1861 nd->seq = set_root_rcu(nd);
1857 } else { 1862 } else {
1858 set_root(nd); 1863 set_root(nd);
1859 path_get(&nd->root); 1864 path_get(&nd->root);
@@ -1904,7 +1909,14 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1904 } 1909 }
1905 1910
1906 nd->inode = nd->path.dentry->d_inode; 1911 nd->inode = nd->path.dentry->d_inode;
1907 return 0; 1912 if (!(flags & LOOKUP_RCU))
1913 return 0;
1914 if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
1915 return 0;
1916 if (!(nd->flags & LOOKUP_ROOT))
1917 nd->root.mnt = NULL;
1918 rcu_read_unlock();
1919 return -ECHILD;
1908} 1920}
1909 1921
1910static inline int lookup_last(struct nameidata *nd, struct path *path) 1922static inline int lookup_last(struct nameidata *nd, struct path *path)