Commit 7ac75979 authored by Andrew Morton's avatar Andrew Morton Committed by Jens Axboe

[PATCH] dcache_rcu: revert fast_walk code

Patch from Maneesh Soni <maneesh@in.ibm.com>

Revert the fast-walk dcache code in preparation for dcache_rcu.
parent 10507a61
...@@ -286,27 +286,6 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, ...@@ -286,27 +286,6 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
return dentry; return dentry;
} }
/*for fastwalking*/
static inline void unlock_nd(struct nameidata *nd)
{
struct vfsmount *mnt = nd->old_mnt;
struct dentry *dentry = nd->old_dentry;
mntget(nd->mnt);
dget_locked(nd->dentry);
nd->old_mnt = NULL;
nd->old_dentry = NULL;
spin_unlock(&dcache_lock);
dput(dentry);
mntput(mnt);
}
static inline void lock_nd(struct nameidata *nd)
{
spin_lock(&dcache_lock);
nd->old_mnt = nd->mnt;
nd->old_dentry = nd->dentry;
}
/* /*
* Short-cut version of permission(), for calling by * Short-cut version of permission(), for calling by
* path_walk(), when dcache lock is held. Combines parts * path_walk(), when dcache lock is held. Combines parts
...@@ -451,11 +430,18 @@ static int follow_mount(struct vfsmount **mnt, struct dentry **dentry) ...@@ -451,11 +430,18 @@ static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
{ {
int res = 0; int res = 0;
while (d_mountpoint(*dentry)) { while (d_mountpoint(*dentry)) {
struct vfsmount *mounted = lookup_mnt(*mnt, *dentry); struct vfsmount *mounted;
if (!mounted) spin_lock(&dcache_lock);
mounted = lookup_mnt(*mnt, *dentry);
if (!mounted) {
spin_unlock(&dcache_lock);
break; break;
*mnt = mounted; }
*dentry = mounted->mnt_root; *mnt = mntget(mounted);
spin_unlock(&dcache_lock);
dput(*dentry);
mntput(mounted->mnt_parent);
*dentry = dget(mounted->mnt_root);
res = 1; res = 1;
} }
return res; return res;
...@@ -488,17 +474,32 @@ static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry) ...@@ -488,17 +474,32 @@ static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
{ {
while(1) { while(1) {
struct vfsmount *parent; struct vfsmount *parent;
struct dentry *old = *dentry;
read_lock(&current->fs->lock);
if (*dentry == current->fs->root && if (*dentry == current->fs->root &&
*mnt == current->fs->rootmnt) *mnt == current->fs->rootmnt) {
read_unlock(&current->fs->lock);
break; break;
}
read_unlock(&current->fs->lock);
spin_lock(&dcache_lock);
if (*dentry != (*mnt)->mnt_root) { if (*dentry != (*mnt)->mnt_root) {
*dentry = (*dentry)->d_parent; *dentry = dget((*dentry)->d_parent);
spin_unlock(&dcache_lock);
dput(old);
break; break;
} }
parent=(*mnt)->mnt_parent; parent = (*mnt)->mnt_parent;
if (parent == *mnt) if (parent == *mnt) {
spin_unlock(&dcache_lock);
break; break;
*dentry=(*mnt)->mnt_mountpoint; }
mntget(parent);
*dentry = dget((*mnt)->mnt_mountpoint);
spin_unlock(&dcache_lock);
dput(old);
mntput(*mnt);
*mnt = parent; *mnt = parent;
} }
follow_mount(mnt, dentry); follow_mount(mnt, dentry);
...@@ -515,14 +516,13 @@ struct path { ...@@ -515,14 +516,13 @@ struct path {
* It _is_ time-critical. * It _is_ time-critical.
*/ */
static int do_lookup(struct nameidata *nd, struct qstr *name, static int do_lookup(struct nameidata *nd, struct qstr *name,
struct path *path, struct path *cached_path, struct path *path, int flags)
int flags)
{ {
struct vfsmount *mnt = nd->mnt; struct vfsmount *mnt = nd->mnt;
struct dentry *dentry = __d_lookup(nd->dentry, name); struct dentry *dentry = d_lookup(nd->dentry, name);
if (!dentry) if (!dentry)
goto dcache_miss; goto need_lookup;
if (dentry->d_op && dentry->d_op->d_revalidate) if (dentry->d_op && dentry->d_op->d_revalidate)
goto need_revalidate; goto need_revalidate;
done: done:
...@@ -530,36 +530,21 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, ...@@ -530,36 +530,21 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
path->dentry = dentry; path->dentry = dentry;
return 0; return 0;
dcache_miss:
unlock_nd(nd);
need_lookup: need_lookup:
dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE); dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
if (IS_ERR(dentry)) if (IS_ERR(dentry))
goto fail; goto fail;
mntget(mnt);
relock:
dput(cached_path->dentry);
mntput(cached_path->mnt);
cached_path->mnt = mnt;
cached_path->dentry = dentry;
lock_nd(nd);
goto done; goto done;
need_revalidate: need_revalidate:
mntget(mnt);
dget_locked(dentry);
unlock_nd(nd);
if (dentry->d_op->d_revalidate(dentry, flags)) if (dentry->d_op->d_revalidate(dentry, flags))
goto relock; goto done;
if (d_invalidate(dentry)) if (d_invalidate(dentry))
goto relock; goto done;
dput(dentry); dput(dentry);
mntput(mnt);
goto need_lookup; goto need_lookup;
fail: fail:
lock_nd(nd);
return PTR_ERR(dentry); return PTR_ERR(dentry);
} }
...@@ -573,7 +558,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, ...@@ -573,7 +558,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
*/ */
int link_path_walk(const char * name, struct nameidata *nd) int link_path_walk(const char * name, struct nameidata *nd)
{ {
struct path next, pinned = {NULL, NULL}; struct path next;
struct inode *inode; struct inode *inode;
int err; int err;
unsigned int lookup_flags = nd->flags; unsigned int lookup_flags = nd->flags;
...@@ -594,10 +579,8 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -594,10 +579,8 @@ int link_path_walk(const char * name, struct nameidata *nd)
unsigned int c; unsigned int c;
err = exec_permission_lite(inode); err = exec_permission_lite(inode);
if (err == -EAGAIN) { if (err == -EAGAIN) {
unlock_nd(nd);
err = permission(inode, MAY_EXEC); err = permission(inode, MAY_EXEC);
lock_nd(nd);
} }
if (err) if (err)
break; break;
...@@ -648,7 +631,7 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -648,7 +631,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
break; break;
} }
/* This does the actual lookups.. */ /* This does the actual lookups.. */
err = do_lookup(nd, &this, &next, &pinned, LOOKUP_CONTINUE); err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE);
if (err) if (err)
break; break;
/* Check mountpoints.. */ /* Check mountpoints.. */
...@@ -657,21 +640,18 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -657,21 +640,18 @@ int link_path_walk(const char * name, struct nameidata *nd)
err = -ENOENT; err = -ENOENT;
inode = next.dentry->d_inode; inode = next.dentry->d_inode;
if (!inode) if (!inode)
break; goto out_dput;
err = -ENOTDIR; err = -ENOTDIR;
if (!inode->i_op) if (!inode->i_op)
break; goto out_dput;
if (inode->i_op->follow_link) { if (inode->i_op->follow_link) {
mntget(next.mnt); mntget(next.mnt);
dget_locked(next.dentry);
unlock_nd(nd);
err = do_follow_link(next.dentry, nd); err = do_follow_link(next.dentry, nd);
dput(next.dentry); dput(next.dentry);
mntput(next.mnt); mntput(next.mnt);
if (err) if (err)
goto return_err; goto return_err;
lock_nd(nd);
err = -ENOENT; err = -ENOENT;
inode = nd->dentry->d_inode; inode = nd->dentry->d_inode;
if (!inode) if (!inode)
...@@ -680,6 +660,7 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -680,6 +660,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
if (!inode->i_op) if (!inode->i_op)
break; break;
} else { } else {
dput(nd->dentry);
nd->mnt = next.mnt; nd->mnt = next.mnt;
nd->dentry = next.dentry; nd->dentry = next.dentry;
} }
...@@ -711,7 +692,7 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -711,7 +692,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
if (err < 0) if (err < 0)
break; break;
} }
err = do_lookup(nd, &this, &next, &pinned, 0); err = do_lookup(nd, &this, &next, 0);
if (err) if (err)
break; break;
follow_mount(&next.mnt, &next.dentry); follow_mount(&next.mnt, &next.dentry);
...@@ -719,16 +700,14 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -719,16 +700,14 @@ int link_path_walk(const char * name, struct nameidata *nd)
if ((lookup_flags & LOOKUP_FOLLOW) if ((lookup_flags & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) { && inode && inode->i_op && inode->i_op->follow_link) {
mntget(next.mnt); mntget(next.mnt);
dget_locked(next.dentry);
unlock_nd(nd);
err = do_follow_link(next.dentry, nd); err = do_follow_link(next.dentry, nd);
dput(next.dentry); dput(next.dentry);
mntput(next.mnt); mntput(next.mnt);
if (err) if (err)
goto return_err; goto return_err;
inode = nd->dentry->d_inode; inode = nd->dentry->d_inode;
lock_nd(nd);
} else { } else {
dput(nd->dentry);
nd->mnt = next.mnt; nd->mnt = next.mnt;
nd->dentry = next.dentry; nd->dentry = next.dentry;
} }
...@@ -751,23 +730,19 @@ int link_path_walk(const char * name, struct nameidata *nd) ...@@ -751,23 +730,19 @@ int link_path_walk(const char * name, struct nameidata *nd)
else if (this.len == 2 && this.name[1] == '.') else if (this.len == 2 && this.name[1] == '.')
nd->last_type = LAST_DOTDOT; nd->last_type = LAST_DOTDOT;
return_base: return_base:
unlock_nd(nd);
dput(pinned.dentry);
mntput(pinned.mnt);
return 0; return 0;
out_dput:
dput(next.dentry);
break;
} }
unlock_nd(nd);
path_release(nd); path_release(nd);
return_err: return_err:
dput(pinned.dentry);
mntput(pinned.mnt);
return err; return err;
} }
int path_walk(const char * name, struct nameidata *nd) int path_walk(const char * name, struct nameidata *nd)
{ {
current->total_link_count = 0; current->total_link_count = 0;
lock_nd(nd);
return link_path_walk(name, nd); return link_path_walk(name, nd);
} }
...@@ -855,28 +830,24 @@ int path_lookup(const char *name, unsigned int flags, struct nameidata *nd) ...@@ -855,28 +830,24 @@ int path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
{ {
nd->last_type = LAST_ROOT; /* if there are only slashes... */ nd->last_type = LAST_ROOT; /* if there are only slashes... */
nd->flags = flags; nd->flags = flags;
read_lock(&current->fs->lock);
if (*name=='/') { if (*name=='/') {
read_lock(&current->fs->lock);
if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) { if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
nd->mnt = mntget(current->fs->altrootmnt); nd->mnt = mntget(current->fs->altrootmnt);
nd->dentry = dget(current->fs->altroot); nd->dentry = dget(current->fs->altroot);
read_unlock(&current->fs->lock); read_unlock(&current->fs->lock);
if (__emul_lookup_dentry(name,nd)) if (__emul_lookup_dentry(name,nd))
return 0; return 0;
} else {
read_unlock(&current->fs->lock);
} }
spin_lock(&dcache_lock); nd->mnt = mntget(current->fs->rootmnt);
nd->mnt = current->fs->rootmnt; nd->dentry = dget(current->fs->root);
nd->dentry = current->fs->root;
} }
else{ else{
spin_lock(&dcache_lock); nd->mnt = mntget(current->fs->pwdmnt);
nd->mnt = current->fs->pwdmnt; nd->dentry = dget(current->fs->pwd);
nd->dentry = current->fs->pwd;
} }
nd->old_mnt = NULL; read_unlock(&current->fs->lock);
nd->old_dentry = NULL;
current->total_link_count = 0; current->total_link_count = 0;
return link_path_walk(name, nd); return link_path_walk(name, nd);
} }
...@@ -2129,7 +2100,6 @@ __vfs_follow_link(struct nameidata *nd, const char *link) ...@@ -2129,7 +2100,6 @@ __vfs_follow_link(struct nameidata *nd, const char *link)
/* weird __emul_prefix() stuff did it */ /* weird __emul_prefix() stuff did it */
goto out; goto out;
} }
lock_nd(nd);
res = link_path_walk(link, nd); res = link_path_walk(link, nd);
out: out:
if (current->link_count || res || nd->last_type!=LAST_NORM) if (current->link_count || res || nd->last_type!=LAST_NORM)
......
...@@ -892,12 +892,10 @@ void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt, ...@@ -892,12 +892,10 @@ void set_fs_root(struct fs_struct *fs, struct vfsmount *mnt,
struct dentry *old_root; struct dentry *old_root;
struct vfsmount *old_rootmnt; struct vfsmount *old_rootmnt;
write_lock(&fs->lock); write_lock(&fs->lock);
spin_lock(&dcache_lock);
old_root = fs->root; old_root = fs->root;
old_rootmnt = fs->rootmnt; old_rootmnt = fs->rootmnt;
fs->rootmnt = mntget(mnt); fs->rootmnt = mntget(mnt);
fs->root = dget(dentry); fs->root = dget(dentry);
spin_unlock(&dcache_lock);
write_unlock(&fs->lock); write_unlock(&fs->lock);
if (old_root) { if (old_root) {
dput(old_root); dput(old_root);
...@@ -916,12 +914,10 @@ void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, ...@@ -916,12 +914,10 @@ void set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt,
struct vfsmount *old_pwdmnt; struct vfsmount *old_pwdmnt;
write_lock(&fs->lock); write_lock(&fs->lock);
spin_lock(&dcache_lock);
old_pwd = fs->pwd; old_pwd = fs->pwd;
old_pwdmnt = fs->pwdmnt; old_pwdmnt = fs->pwdmnt;
fs->pwdmnt = mntget(mnt); fs->pwdmnt = mntget(mnt);
fs->pwd = dget(dentry); fs->pwd = dget(dentry);
spin_unlock(&dcache_lock);
write_unlock(&fs->lock); write_unlock(&fs->lock);
if (old_pwd) { if (old_pwd) {
......
...@@ -11,8 +11,6 @@ struct nameidata { ...@@ -11,8 +11,6 @@ struct nameidata {
struct qstr last; struct qstr last;
unsigned int flags; unsigned int flags;
int last_type; int last_type;
struct dentry *old_dentry;
struct vfsmount *old_mnt;
}; };
/* /*
......
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