diff options
author | Al Viro <viro@www.linux.org.uk> | 2005-06-06 13:36:13 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-06 14:42:27 -0700 |
commit | 58c465eba4d7ed307c4c7cb3382ba7ee565e8858 (patch) | |
tree | f147af3fee122ec5cc054ac78fa30e1490a8acd0 /fs/namei.c | |
parent | 39ca6d49759346d4710c759d443eec8048b27213 (diff) |
[PATCH] namei fixes (17/19)
follow_mount() made void, reordered dput()/mntput() in it.
follow_dotdot() switched from struct vfmount ** + struct dentry ** to
struct nameidata *; callers updated.
Equivalent transformation + fix for too-early-mntput() race.
Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/fs/namei.c b/fs/namei.c index 444086d441e1..36925ff307b3 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -596,20 +596,17 @@ static int __follow_mount(struct path *path) return res; } -static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) +static void follow_mount(struct vfsmount **mnt, struct dentry **dentry) { - int res = 0; while (d_mountpoint(*dentry)) { struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); if (!mounted) break; + dput(*dentry); mntput(*mnt); *mnt = mounted; - dput(*dentry); *dentry = dget(mounted->mnt_root); - res = 1; } - return res; } /* no need for dcache_lock, as serialization is taken care in @@ -630,41 +627,41 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry) return 0; } -static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) +static inline void follow_dotdot(struct nameidata *nd) { while(1) { struct vfsmount *parent; - struct dentry *old = *dentry; + struct dentry *old = nd->dentry; read_lock(¤t->fs->lock); - if (*dentry == current->fs->root && - *mnt == current->fs->rootmnt) { + if (nd->dentry == current->fs->root && + nd->mnt == current->fs->rootmnt) { read_unlock(¤t->fs->lock); break; } read_unlock(¤t->fs->lock); spin_lock(&dcache_lock); - if (*dentry != (*mnt)->mnt_root) { - *dentry = dget((*dentry)->d_parent); + if (nd->dentry != nd->mnt->mnt_root) { + nd->dentry = dget(nd->dentry->d_parent); spin_unlock(&dcache_lock); dput(old); break; } spin_unlock(&dcache_lock); spin_lock(&vfsmount_lock); - parent = (*mnt)->mnt_parent; - if (parent == *mnt) { + parent = nd->mnt->mnt_parent; + if (parent == nd->mnt) { spin_unlock(&vfsmount_lock); break; } mntget(parent); - *dentry = dget((*mnt)->mnt_mountpoint); + nd->dentry = dget(nd->mnt->mnt_mountpoint); spin_unlock(&vfsmount_lock); dput(old); - mntput(*mnt); - *mnt = parent; + mntput(nd->mnt); + nd->mnt = parent; } - follow_mount(mnt, dentry); + follow_mount(&nd->mnt, &nd->dentry); } /* @@ -772,7 +769,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) case 2: if (this.name[1] != '.') break; - follow_dotdot(&nd->mnt, &nd->dentry); + follow_dotdot(nd); inode = nd->dentry->d_inode; /* fallthrough */ case 1: @@ -839,7 +836,7 @@ last_component: case 2: if (this.name[1] != '.') break; - follow_dotdot(&nd->mnt, &nd->dentry); + follow_dotdot(nd); inode = nd->dentry->d_inode; /* fallthrough */ case 1: |