Commit 5f833af7 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] namei.c: take vfsmount_lock

From: Mike Waychison <Michael.Waychison@Sun.COM>

The attached patch ensures that we grab vfsmount_lock when grabbing a
reference to mnt_parent in follow_up and follow_dotdot.

We also don't need to access ->mnt_parent in follow_mount and
__follow_down to mntput because we already the parent pointer on the stack.
parent 122eace8
...@@ -420,15 +420,15 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry) ...@@ -420,15 +420,15 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry)
{ {
struct vfsmount *parent; struct vfsmount *parent;
struct dentry *mountpoint; struct dentry *mountpoint;
spin_lock(&dcache_lock); spin_lock(&vfsmount_lock);
parent=(*mnt)->mnt_parent; parent=(*mnt)->mnt_parent;
if (parent == *mnt) { if (parent == *mnt) {
spin_unlock(&dcache_lock); spin_unlock(&vfsmount_lock);
return 0; return 0;
} }
mntget(parent); mntget(parent);
mountpoint=dget((*mnt)->mnt_mountpoint); mountpoint=dget((*mnt)->mnt_mountpoint);
spin_unlock(&dcache_lock); spin_unlock(&vfsmount_lock);
dput(*dentry); dput(*dentry);
*dentry = mountpoint; *dentry = mountpoint;
mntput(*mnt); mntput(*mnt);
...@@ -446,9 +446,9 @@ static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) ...@@ -446,9 +446,9 @@ static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
if (!mounted) if (!mounted)
break; break;
mntput(*mnt);
*mnt = mounted; *mnt = mounted;
dput(*dentry); dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root); *dentry = dget(mounted->mnt_root);
res = 1; res = 1;
} }
...@@ -464,9 +464,9 @@ static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry) ...@@ -464,9 +464,9 @@ static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
mounted = lookup_mnt(*mnt, *dentry); mounted = lookup_mnt(*mnt, *dentry);
if (mounted) { if (mounted) {
mntput(*mnt);
*mnt = mounted; *mnt = mounted;
dput(*dentry); dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root); *dentry = dget(mounted->mnt_root);
return 1; return 1;
} }
...@@ -498,14 +498,16 @@ static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) ...@@ -498,14 +498,16 @@ static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
dput(old); dput(old);
break; break;
} }
spin_unlock(&dcache_lock);
spin_lock(&vfsmount_lock);
parent = (*mnt)->mnt_parent; parent = (*mnt)->mnt_parent;
if (parent == *mnt) { if (parent == *mnt) {
spin_unlock(&dcache_lock); spin_unlock(&vfsmount_lock);
break; break;
} }
mntget(parent); mntget(parent);
*dentry = dget((*mnt)->mnt_mountpoint); *dentry = dget((*mnt)->mnt_mountpoint);
spin_unlock(&dcache_lock); spin_unlock(&vfsmount_lock);
dput(old); dput(old);
mntput(*mnt); mntput(*mnt);
*mnt = parent; *mnt = parent;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment