Commit e4d478f7 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] __vfs_follow_link() made inline again

__vfs_follow_link() really should be inline; that's a special case since
we are in the middle of recursion and really want to conserve stack
space.  Moved before the first use, made inline again.
parent 486198fb
......@@ -408,7 +408,61 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, s
return result;
}
static int __vfs_follow_link(struct nameidata *, const char *);
static int __emul_lookup_dentry(const char *, struct nameidata *);
/* SMP-safe */
static inline int
walk_init_root(const char *name, struct nameidata *nd)
{
read_lock(&current->fs->lock);
if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
nd->mnt = mntget(current->fs->altrootmnt);
nd->dentry = dget(current->fs->altroot);
read_unlock(&current->fs->lock);
if (__emul_lookup_dentry(name,nd))
return 0;
read_lock(&current->fs->lock);
}
nd->mnt = mntget(current->fs->rootmnt);
nd->dentry = dget(current->fs->root);
read_unlock(&current->fs->lock);
return 1;
}
static inline int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
char *name;
if (IS_ERR(link))
goto fail;
if (*link == '/') {
path_release(nd);
if (!walk_init_root(link, nd))
/* weird __emul_prefix() stuff did it */
goto out;
}
res = link_path_walk(link, nd);
out:
if (nd->depth || res || nd->last_type!=LAST_NORM)
return res;
/*
* If it is an iterative symlinks resolution in open_namei() we
* have to copy the last component. And all that crap because of
* bloody create() on broken symlinks. Furrfu...
*/
name = __getname();
if (unlikely(!name)) {
path_release(nd);
return -ENOMEM;
}
strcpy(name, nd->last.name);
nd->last.name = name;
return 0;
fail:
path_release(nd);
return PTR_ERR(link);
}
/*
* This limits recursive symlink follows to 8, while
......@@ -869,25 +923,6 @@ void set_fs_altroot(void)
}
}
/* SMP-safe */
static inline int
walk_init_root(const char *name, struct nameidata *nd)
{
read_lock(&current->fs->lock);
if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
nd->mnt = mntget(current->fs->altrootmnt);
nd->dentry = dget(current->fs->altroot);
read_unlock(&current->fs->lock);
if (__emul_lookup_dentry(name,nd))
return 0;
read_lock(&current->fs->lock);
}
nd->mnt = mntget(current->fs->rootmnt);
nd->dentry = dget(current->fs->root);
read_unlock(&current->fs->lock);
return 1;
}
int fastcall path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
{
int retval;
......@@ -2221,41 +2256,6 @@ int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
return res;
}
static int __vfs_follow_link(struct nameidata *nd, const char *link)
{
int res = 0;
char *name;
if (IS_ERR(link))
goto fail;
if (*link == '/') {
path_release(nd);
if (!walk_init_root(link, nd))
/* weird __emul_prefix() stuff did it */
goto out;
}
res = link_path_walk(link, nd);
out:
if (nd->depth || res || nd->last_type!=LAST_NORM)
return res;
/*
* If it is an iterative symlinks resolution in open_namei() we
* have to copy the last component. And all that crap because of
* bloody create() on broken symlinks. Furrfu...
*/
name = __getname();
if (unlikely(!name)) {
path_release(nd);
return -ENOMEM;
}
strcpy(name, nd->last.name);
nd->last.name = name;
return 0;
fail:
path_release(nd);
return PTR_ERR(link);
}
int vfs_follow_link(struct nameidata *nd, const char *link)
{
return __vfs_follow_link(nd, link);
......
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