summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/namespace.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index 443b0fa564c4..f91a60e6039d 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2318,30 +2318,37 @@ static int attach_recursive_mnt(struct mount *source_mnt,
static struct mountpoint *lock_mount(struct path *path)
{
struct vfsmount *mnt;
- struct dentry *dentry = path->dentry;
-retry:
- inode_lock(dentry->d_inode);
- if (unlikely(cant_mount(dentry))) {
- inode_unlock(dentry->d_inode);
- return ERR_PTR(-ENOENT);
- }
- namespace_lock();
- mnt = lookup_mnt(path);
- if (likely(!mnt)) {
- struct mountpoint *mp = get_mountpoint(dentry);
- if (IS_ERR(mp)) {
- namespace_unlock();
+ struct dentry *dentry;
+ struct mountpoint *mp;
+
+ for (;;) {
+ dentry = path->dentry;
+ inode_lock(dentry->d_inode);
+ if (unlikely(cant_mount(dentry))) {
inode_unlock(dentry->d_inode);
- return mp;
+ return ERR_PTR(-ENOENT);
}
- return mp;
+
+ namespace_lock();
+
+ mnt = lookup_mnt(path);
+ if (likely(!mnt))
+ break;
+
+ namespace_unlock();
+ inode_unlock(dentry->d_inode);
+ path_put(path);
+ path->mnt = mnt;
+ path->dentry = dget(mnt->mnt_root);
}
- namespace_unlock();
- inode_unlock(path->dentry->d_inode);
- path_put(path);
- path->mnt = mnt;
- dentry = path->dentry = dget(mnt->mnt_root);
- goto retry;
+
+ mp = get_mountpoint(dentry);
+ if (IS_ERR(mp)) {
+ namespace_unlock();
+ inode_unlock(dentry->d_inode);
+ }
+
+ return mp;
}
static void unlock_mount(struct mountpoint *where)