x86, hyperv: Mark the Hyper-V clocksource as being continuous
[pandora-kernel.git] / fs / namei.c
index 4945ef6..dea2dab 100644 (file)
@@ -911,21 +911,9 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
        return true;
 }
 
-static void follow_mount_rcu(struct nameidata *nd)
-{
-       while (d_mountpoint(nd->path.dentry)) {
-               struct vfsmount *mounted;
-               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
-               if (!mounted)
-                       break;
-               nd->path.mnt = mounted;
-               nd->path.dentry = mounted->mnt_root;
-               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
-       }
-}
-
 static int follow_dotdot_rcu(struct nameidata *nd)
 {
+       struct inode *inode = nd->inode;
        if (!nd->root.mnt)
                set_root_rcu(nd);
 
@@ -939,6 +927,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
                        struct dentry *parent = old->d_parent;
                        unsigned seq;
 
+                       inode = parent->d_inode;
                        seq = read_seqcount_begin(&parent->d_seq);
                        if (read_seqcount_retry(&old->d_seq, nd->seq))
                                goto failed;
@@ -948,10 +937,20 @@ static int follow_dotdot_rcu(struct nameidata *nd)
                }
                if (!follow_up_rcu(&nd->path))
                        break;
+               inode = nd->path.dentry->d_inode;
                nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
        }
-       follow_mount_rcu(nd);
-       nd->inode = nd->path.dentry->d_inode;
+       while (d_mountpoint(nd->path.dentry)) {
+               struct vfsmount *mounted;
+               mounted = __lookup_mnt(nd->path.mnt, nd->path.dentry, 1);
+               if (!mounted)
+                       break;
+               nd->path.mnt = mounted;
+               nd->path.dentry = mounted->mnt_root;
+               inode = nd->path.dentry->d_inode;
+               nd->seq = read_seqcount_begin(&nd->path.dentry->d_seq);
+       }
+       nd->inode = inode;
        return 0;
 
 failed:
@@ -1561,7 +1560,14 @@ static int path_init(int dfd, const char *name, unsigned int flags,
        }
 
        nd->inode = nd->path.dentry->d_inode;
-       return 0;
+       if (!(flags & LOOKUP_RCU))
+               return 0;
+       if (likely(!read_seqcount_retry(&nd->path.dentry->d_seq, nd->seq)))
+               return 0;
+       if (!(nd->flags & LOOKUP_ROOT))
+               nd->root.mnt = NULL;
+       rcu_read_unlock();
+       return -ECHILD;
 
 fput_fail:
        fput_light(file, fput_needed);