Embed a struct path into struct nameidata instead of nd->{dentry,mnt}
This is the central patch of a cleanup series. In most cases there is no good
reason why someone would want to use a dentry for itself. This series reflects
that fact and embeds a struct path into nameidata.
Together with the other patches of this series
- it enforced the correct order of getting/releasing the reference count on
<dentry,vfsmount> pairs
- it prepares the VFS for stacking support since it is essential to have a
struct path in every place where the stack can be traversed
- it reduces the overall code size:
without patch series:
text data bss dec hex filename
5321639 858418 715768 6895825 6938d1 vmlinux
with patch series:
text data bss dec hex filename
5320026 858418 715768 6894212
693284 vmlinux
This patch:
Switch from nd->{dentry,mnt} to nd->path.{dentry,mnt} everywhere.
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: fix cifs]
[akpm@linux-foundation.org: fix smack]
Signed-off-by: Jan Blunck <jblunck@suse.de>
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
c5e725f33b
commit
4ac9137858
220
fs/namei.c
220
fs/namei.c
@@ -231,7 +231,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
struct vfsmount *mnt = NULL;
|
||||
|
||||
if (nd)
|
||||
mnt = nd->mnt;
|
||||
mnt = nd->path.mnt;
|
||||
|
||||
if (mask & MAY_WRITE) {
|
||||
umode_t mode = inode->i_mode;
|
||||
@@ -296,7 +296,7 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
|
||||
*/
|
||||
int vfs_permission(struct nameidata *nd, int mask)
|
||||
{
|
||||
return permission(nd->dentry->d_inode, mask, nd);
|
||||
return permission(nd->path.dentry->d_inode, mask, nd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,8 +364,8 @@ int deny_write_access(struct file * file)
|
||||
|
||||
void path_release(struct nameidata *nd)
|
||||
{
|
||||
dput(nd->dentry);
|
||||
mntput(nd->mnt);
|
||||
dput(nd->path.dentry);
|
||||
mntput(nd->path.mnt);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -530,15 +530,15 @@ walk_init_root(const char *name, struct nameidata *nd)
|
||||
|
||||
read_lock(&fs->lock);
|
||||
if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
|
||||
nd->mnt = mntget(fs->altrootmnt);
|
||||
nd->dentry = dget(fs->altroot);
|
||||
nd->path.mnt = mntget(fs->altrootmnt);
|
||||
nd->path.dentry = dget(fs->altroot);
|
||||
read_unlock(&fs->lock);
|
||||
if (__emul_lookup_dentry(name,nd))
|
||||
return 0;
|
||||
read_lock(&fs->lock);
|
||||
}
|
||||
nd->mnt = mntget(fs->rootmnt);
|
||||
nd->dentry = dget(fs->root);
|
||||
nd->path.mnt = mntget(fs->rootmnt);
|
||||
nd->path.dentry = dget(fs->root);
|
||||
read_unlock(&fs->lock);
|
||||
return 1;
|
||||
}
|
||||
@@ -581,17 +581,17 @@ fail:
|
||||
static inline void dput_path(struct path *path, struct nameidata *nd)
|
||||
{
|
||||
dput(path->dentry);
|
||||
if (path->mnt != nd->mnt)
|
||||
if (path->mnt != nd->path.mnt)
|
||||
mntput(path->mnt);
|
||||
}
|
||||
|
||||
static inline void path_to_nameidata(struct path *path, struct nameidata *nd)
|
||||
{
|
||||
dput(nd->dentry);
|
||||
if (nd->mnt != path->mnt)
|
||||
mntput(nd->mnt);
|
||||
nd->mnt = path->mnt;
|
||||
nd->dentry = path->dentry;
|
||||
dput(nd->path.dentry);
|
||||
if (nd->path.mnt != path->mnt)
|
||||
mntput(nd->path.mnt);
|
||||
nd->path.mnt = path->mnt;
|
||||
nd->path.dentry = path->dentry;
|
||||
}
|
||||
|
||||
static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
|
||||
@@ -603,7 +603,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
|
||||
touch_atime(path->mnt, dentry);
|
||||
nd_set_link(nd, NULL);
|
||||
|
||||
if (path->mnt != nd->mnt) {
|
||||
if (path->mnt != nd->path.mnt) {
|
||||
path_to_nameidata(path, nd);
|
||||
dget(dentry);
|
||||
}
|
||||
@@ -733,37 +733,37 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
|
||||
|
||||
while(1) {
|
||||
struct vfsmount *parent;
|
||||
struct dentry *old = nd->dentry;
|
||||
struct dentry *old = nd->path.dentry;
|
||||
|
||||
read_lock(&fs->lock);
|
||||
if (nd->dentry == fs->root &&
|
||||
nd->mnt == fs->rootmnt) {
|
||||
if (nd->path.dentry == fs->root &&
|
||||
nd->path.mnt == fs->rootmnt) {
|
||||
read_unlock(&fs->lock);
|
||||
break;
|
||||
}
|
||||
read_unlock(&fs->lock);
|
||||
spin_lock(&dcache_lock);
|
||||
if (nd->dentry != nd->mnt->mnt_root) {
|
||||
nd->dentry = dget(nd->dentry->d_parent);
|
||||
if (nd->path.dentry != nd->path.mnt->mnt_root) {
|
||||
nd->path.dentry = dget(nd->path.dentry->d_parent);
|
||||
spin_unlock(&dcache_lock);
|
||||
dput(old);
|
||||
break;
|
||||
}
|
||||
spin_unlock(&dcache_lock);
|
||||
spin_lock(&vfsmount_lock);
|
||||
parent = nd->mnt->mnt_parent;
|
||||
if (parent == nd->mnt) {
|
||||
parent = nd->path.mnt->mnt_parent;
|
||||
if (parent == nd->path.mnt) {
|
||||
spin_unlock(&vfsmount_lock);
|
||||
break;
|
||||
}
|
||||
mntget(parent);
|
||||
nd->dentry = dget(nd->mnt->mnt_mountpoint);
|
||||
nd->path.dentry = dget(nd->path.mnt->mnt_mountpoint);
|
||||
spin_unlock(&vfsmount_lock);
|
||||
dput(old);
|
||||
mntput(nd->mnt);
|
||||
nd->mnt = parent;
|
||||
mntput(nd->path.mnt);
|
||||
nd->path.mnt = parent;
|
||||
}
|
||||
follow_mount(&nd->mnt, &nd->dentry);
|
||||
follow_mount(&nd->path.mnt, &nd->path.dentry);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -774,8 +774,8 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
|
||||
static int do_lookup(struct nameidata *nd, struct qstr *name,
|
||||
struct path *path)
|
||||
{
|
||||
struct vfsmount *mnt = nd->mnt;
|
||||
struct dentry *dentry = __d_lookup(nd->dentry, name);
|
||||
struct vfsmount *mnt = nd->path.mnt;
|
||||
struct dentry *dentry = __d_lookup(nd->path.dentry, name);
|
||||
|
||||
if (!dentry)
|
||||
goto need_lookup;
|
||||
@@ -788,7 +788,7 @@ done:
|
||||
return 0;
|
||||
|
||||
need_lookup:
|
||||
dentry = real_lookup(nd->dentry, name, nd);
|
||||
dentry = real_lookup(nd->path.dentry, name, nd);
|
||||
if (IS_ERR(dentry))
|
||||
goto fail;
|
||||
goto done;
|
||||
@@ -825,7 +825,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
|
||||
if (!*name)
|
||||
goto return_reval;
|
||||
|
||||
inode = nd->dentry->d_inode;
|
||||
inode = nd->path.dentry->d_inode;
|
||||
if (nd->depth)
|
||||
lookup_flags = LOOKUP_FOLLOW | (nd->flags & LOOKUP_CONTINUE);
|
||||
|
||||
@@ -873,7 +873,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
|
||||
if (this.name[1] != '.')
|
||||
break;
|
||||
follow_dotdot(nd);
|
||||
inode = nd->dentry->d_inode;
|
||||
inode = nd->path.dentry->d_inode;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
continue;
|
||||
@@ -882,8 +882,9 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
|
||||
* See if the low-level filesystem might want
|
||||
* to use its own hash..
|
||||
*/
|
||||
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
|
||||
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
|
||||
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
|
||||
err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
|
||||
&this);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
@@ -905,7 +906,7 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
|
||||
if (err)
|
||||
goto return_err;
|
||||
err = -ENOENT;
|
||||
inode = nd->dentry->d_inode;
|
||||
inode = nd->path.dentry->d_inode;
|
||||
if (!inode)
|
||||
break;
|
||||
err = -ENOTDIR;
|
||||
@@ -933,13 +934,14 @@ last_component:
|
||||
if (this.name[1] != '.')
|
||||
break;
|
||||
follow_dotdot(nd);
|
||||
inode = nd->dentry->d_inode;
|
||||
inode = nd->path.dentry->d_inode;
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
goto return_reval;
|
||||
}
|
||||
if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
|
||||
err = nd->dentry->d_op->d_hash(nd->dentry, &this);
|
||||
if (nd->path.dentry->d_op && nd->path.dentry->d_op->d_hash) {
|
||||
err = nd->path.dentry->d_op->d_hash(nd->path.dentry,
|
||||
&this);
|
||||
if (err < 0)
|
||||
break;
|
||||
}
|
||||
@@ -952,7 +954,7 @@ last_component:
|
||||
err = do_follow_link(&next, nd);
|
||||
if (err)
|
||||
goto return_err;
|
||||
inode = nd->dentry->d_inode;
|
||||
inode = nd->path.dentry->d_inode;
|
||||
} else
|
||||
path_to_nameidata(&next, nd);
|
||||
err = -ENOENT;
|
||||
@@ -980,11 +982,12 @@ return_reval:
|
||||
* We bypassed the ordinary revalidation routines.
|
||||
* We may need to check the cached dentry for staleness.
|
||||
*/
|
||||
if (nd->dentry && nd->dentry->d_sb &&
|
||||
(nd->dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
|
||||
if (nd->path.dentry && nd->path.dentry->d_sb &&
|
||||
(nd->path.dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT)) {
|
||||
err = -ESTALE;
|
||||
/* Note: we do not d_invalidate() */
|
||||
if (!nd->dentry->d_op->d_revalidate(nd->dentry, nd))
|
||||
if (!nd->path.dentry->d_op->d_revalidate(
|
||||
nd->path.dentry, nd))
|
||||
break;
|
||||
}
|
||||
return_base:
|
||||
@@ -1011,20 +1014,20 @@ static int link_path_walk(const char *name, struct nameidata *nd)
|
||||
int result;
|
||||
|
||||
/* make sure the stuff we saved doesn't go away */
|
||||
dget(save.dentry);
|
||||
mntget(save.mnt);
|
||||
dget(save.path.dentry);
|
||||
mntget(save.path.mnt);
|
||||
|
||||
result = __link_path_walk(name, nd);
|
||||
if (result == -ESTALE) {
|
||||
*nd = save;
|
||||
dget(nd->dentry);
|
||||
mntget(nd->mnt);
|
||||
dget(nd->path.dentry);
|
||||
mntget(nd->path.mnt);
|
||||
nd->flags |= LOOKUP_REVAL;
|
||||
result = __link_path_walk(name, nd);
|
||||
}
|
||||
|
||||
dput(save.dentry);
|
||||
mntput(save.mnt);
|
||||
dput(save.path.dentry);
|
||||
mntput(save.path.mnt);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1044,9 +1047,10 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
|
||||
if (path_walk(name, nd))
|
||||
return 0; /* something went wrong... */
|
||||
|
||||
if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {
|
||||
struct dentry *old_dentry = nd->dentry;
|
||||
struct vfsmount *old_mnt = nd->mnt;
|
||||
if (!nd->path.dentry->d_inode ||
|
||||
S_ISDIR(nd->path.dentry->d_inode->i_mode)) {
|
||||
struct dentry *old_dentry = nd->path.dentry;
|
||||
struct vfsmount *old_mnt = nd->path.mnt;
|
||||
struct qstr last = nd->last;
|
||||
int last_type = nd->last_type;
|
||||
struct fs_struct *fs = current->fs;
|
||||
@@ -1057,19 +1061,19 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
|
||||
*/
|
||||
nd->last_type = LAST_ROOT;
|
||||
read_lock(&fs->lock);
|
||||
nd->mnt = mntget(fs->rootmnt);
|
||||
nd->dentry = dget(fs->root);
|
||||
nd->path.mnt = mntget(fs->rootmnt);
|
||||
nd->path.dentry = dget(fs->root);
|
||||
read_unlock(&fs->lock);
|
||||
if (path_walk(name, nd) == 0) {
|
||||
if (nd->dentry->d_inode) {
|
||||
if (nd->path.dentry->d_inode) {
|
||||
dput(old_dentry);
|
||||
mntput(old_mnt);
|
||||
return 1;
|
||||
}
|
||||
path_release(nd);
|
||||
}
|
||||
nd->dentry = old_dentry;
|
||||
nd->mnt = old_mnt;
|
||||
nd->path.dentry = old_dentry;
|
||||
nd->path.mnt = old_mnt;
|
||||
nd->last = last;
|
||||
nd->last_type = last_type;
|
||||
}
|
||||
@@ -1089,8 +1093,8 @@ void set_fs_altroot(void)
|
||||
goto set_it;
|
||||
err = path_lookup(emul, LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_NOALT, &nd);
|
||||
if (!err) {
|
||||
mnt = nd.mnt;
|
||||
dentry = nd.dentry;
|
||||
mnt = nd.path.mnt;
|
||||
dentry = nd.path.dentry;
|
||||
}
|
||||
set_it:
|
||||
write_lock(&fs->lock);
|
||||
@@ -1121,20 +1125,20 @@ static int do_path_lookup(int dfd, const char *name,
|
||||
if (*name=='/') {
|
||||
read_lock(&fs->lock);
|
||||
if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
|
||||
nd->mnt = mntget(fs->altrootmnt);
|
||||
nd->dentry = dget(fs->altroot);
|
||||
nd->path.mnt = mntget(fs->altrootmnt);
|
||||
nd->path.dentry = dget(fs->altroot);
|
||||
read_unlock(&fs->lock);
|
||||
if (__emul_lookup_dentry(name,nd))
|
||||
goto out; /* found in altroot */
|
||||
read_lock(&fs->lock);
|
||||
}
|
||||
nd->mnt = mntget(fs->rootmnt);
|
||||
nd->dentry = dget(fs->root);
|
||||
nd->path.mnt = mntget(fs->rootmnt);
|
||||
nd->path.dentry = dget(fs->root);
|
||||
read_unlock(&fs->lock);
|
||||
} else if (dfd == AT_FDCWD) {
|
||||
read_lock(&fs->lock);
|
||||
nd->mnt = mntget(fs->pwdmnt);
|
||||
nd->dentry = dget(fs->pwd);
|
||||
nd->path.mnt = mntget(fs->pwdmnt);
|
||||
nd->path.dentry = dget(fs->pwd);
|
||||
read_unlock(&fs->lock);
|
||||
} else {
|
||||
struct dentry *dentry;
|
||||
@@ -1154,17 +1158,17 @@ static int do_path_lookup(int dfd, const char *name,
|
||||
if (retval)
|
||||
goto fput_fail;
|
||||
|
||||
nd->mnt = mntget(file->f_path.mnt);
|
||||
nd->dentry = dget(dentry);
|
||||
nd->path.mnt = mntget(file->f_path.mnt);
|
||||
nd->path.dentry = dget(dentry);
|
||||
|
||||
fput_light(file, fput_needed);
|
||||
}
|
||||
|
||||
retval = path_walk(name, nd);
|
||||
out:
|
||||
if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
|
||||
nd->dentry->d_inode))
|
||||
audit_inode(name, nd->dentry);
|
||||
if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
|
||||
nd->path.dentry->d_inode))
|
||||
audit_inode(name, nd->path.dentry);
|
||||
out_fail:
|
||||
return retval;
|
||||
|
||||
@@ -1198,13 +1202,13 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
|
||||
nd->flags = flags;
|
||||
nd->depth = 0;
|
||||
|
||||
nd->mnt = mntget(mnt);
|
||||
nd->dentry = dget(dentry);
|
||||
nd->path.mnt = mntget(mnt);
|
||||
nd->path.dentry = dget(dentry);
|
||||
|
||||
retval = path_walk(name, nd);
|
||||
if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
|
||||
nd->dentry->d_inode))
|
||||
audit_inode(name, nd->dentry);
|
||||
if (unlikely(!retval && !audit_dummy_context() && nd->path.dentry &&
|
||||
nd->path.dentry->d_inode))
|
||||
audit_inode(name, nd->path.dentry);
|
||||
|
||||
return retval;
|
||||
|
||||
@@ -1323,10 +1327,10 @@ static struct dentry *lookup_hash(struct nameidata *nd)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = permission(nd->dentry->d_inode, MAY_EXEC, nd);
|
||||
err = permission(nd->path.dentry->d_inode, MAY_EXEC, nd);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
return __lookup_hash(&nd->last, nd->dentry, nd);
|
||||
return __lookup_hash(&nd->last, nd->path.dentry, nd);
|
||||
}
|
||||
|
||||
static int __lookup_one_len(const char *name, struct qstr *this,
|
||||
@@ -1585,7 +1589,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
|
||||
|
||||
int may_open(struct nameidata *nd, int acc_mode, int flag)
|
||||
{
|
||||
struct dentry *dentry = nd->dentry;
|
||||
struct dentry *dentry = nd->path.dentry;
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
|
||||
@@ -1606,7 +1610,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
|
||||
if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
|
||||
flag &= ~O_TRUNC;
|
||||
} else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
|
||||
if (nd->mnt->mnt_flags & MNT_NODEV)
|
||||
if (nd->path.mnt->mnt_flags & MNT_NODEV)
|
||||
return -EACCES;
|
||||
|
||||
flag &= ~O_TRUNC;
|
||||
@@ -1668,14 +1672,14 @@ static int open_namei_create(struct nameidata *nd, struct path *path,
|
||||
int flag, int mode)
|
||||
{
|
||||
int error;
|
||||
struct dentry *dir = nd->dentry;
|
||||
struct dentry *dir = nd->path.dentry;
|
||||
|
||||
if (!IS_POSIXACL(dir->d_inode))
|
||||
mode &= ~current->fs->umask;
|
||||
error = vfs_create(dir->d_inode, path->dentry, mode, nd);
|
||||
mutex_unlock(&dir->d_inode->i_mutex);
|
||||
dput(nd->dentry);
|
||||
nd->dentry = path->dentry;
|
||||
dput(nd->path.dentry);
|
||||
nd->path.dentry = path->dentry;
|
||||
if (error)
|
||||
return error;
|
||||
/* Don't check for write permission, don't truncate */
|
||||
@@ -1742,11 +1746,11 @@ int open_namei(int dfd, const char *pathname, int flag,
|
||||
if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])
|
||||
goto exit;
|
||||
|
||||
dir = nd->dentry;
|
||||
dir = nd->path.dentry;
|
||||
nd->flags &= ~LOOKUP_PARENT;
|
||||
mutex_lock(&dir->d_inode->i_mutex);
|
||||
path.dentry = lookup_hash(nd);
|
||||
path.mnt = nd->mnt;
|
||||
path.mnt = nd->path.mnt;
|
||||
|
||||
do_last:
|
||||
error = PTR_ERR(path.dentry);
|
||||
@@ -1851,10 +1855,10 @@ do_link:
|
||||
__putname(nd->last.name);
|
||||
goto exit;
|
||||
}
|
||||
dir = nd->dentry;
|
||||
dir = nd->path.dentry;
|
||||
mutex_lock(&dir->d_inode->i_mutex);
|
||||
path.dentry = lookup_hash(nd);
|
||||
path.mnt = nd->mnt;
|
||||
path.mnt = nd->path.mnt;
|
||||
__putname(nd->last.name);
|
||||
goto do_last;
|
||||
}
|
||||
@@ -1867,13 +1871,13 @@ do_link:
|
||||
* Simple function to lookup and return a dentry and create it
|
||||
* if it doesn't exist. Is SMP-safe.
|
||||
*
|
||||
* Returns with nd->dentry->d_inode->i_mutex locked.
|
||||
* Returns with nd->path.dentry->d_inode->i_mutex locked.
|
||||
*/
|
||||
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
|
||||
{
|
||||
struct dentry *dentry = ERR_PTR(-EEXIST);
|
||||
|
||||
mutex_lock_nested(&nd->dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&nd->path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
/*
|
||||
* Yucky last component or no last component at all?
|
||||
* (foo/., foo/.., /////)
|
||||
@@ -1952,19 +1956,19 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
|
||||
dentry = lookup_create(&nd, 0);
|
||||
error = PTR_ERR(dentry);
|
||||
|
||||
if (!IS_POSIXACL(nd.dentry->d_inode))
|
||||
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
||||
mode &= ~current->fs->umask;
|
||||
if (!IS_ERR(dentry)) {
|
||||
switch (mode & S_IFMT) {
|
||||
case 0: case S_IFREG:
|
||||
error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
|
||||
error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
|
||||
break;
|
||||
case S_IFCHR: case S_IFBLK:
|
||||
error = vfs_mknod(nd.dentry->d_inode,dentry,mode,
|
||||
error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,
|
||||
new_decode_dev(dev));
|
||||
break;
|
||||
case S_IFIFO: case S_IFSOCK:
|
||||
error = vfs_mknod(nd.dentry->d_inode,dentry,mode,0);
|
||||
error = vfs_mknod(nd.path.dentry->d_inode,dentry,mode,0);
|
||||
break;
|
||||
case S_IFDIR:
|
||||
error = -EPERM;
|
||||
@@ -1974,7 +1978,7 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
|
||||
}
|
||||
dput(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_release(&nd);
|
||||
out:
|
||||
putname(tmp);
|
||||
@@ -2029,12 +2033,12 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
|
||||
if (IS_ERR(dentry))
|
||||
goto out_unlock;
|
||||
|
||||
if (!IS_POSIXACL(nd.dentry->d_inode))
|
||||
if (!IS_POSIXACL(nd.path.dentry->d_inode))
|
||||
mode &= ~current->fs->umask;
|
||||
error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
|
||||
error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode);
|
||||
dput(dentry);
|
||||
out_unlock:
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_release(&nd);
|
||||
out:
|
||||
putname(tmp);
|
||||
@@ -2133,15 +2137,15 @@ static long do_rmdir(int dfd, const char __user *pathname)
|
||||
error = -EBUSY;
|
||||
goto exit1;
|
||||
}
|
||||
mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
dentry = lookup_hash(&nd);
|
||||
error = PTR_ERR(dentry);
|
||||
if (IS_ERR(dentry))
|
||||
goto exit2;
|
||||
error = vfs_rmdir(nd.dentry->d_inode, dentry);
|
||||
error = vfs_rmdir(nd.path.dentry->d_inode, dentry);
|
||||
dput(dentry);
|
||||
exit2:
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
exit1:
|
||||
path_release(&nd);
|
||||
exit:
|
||||
@@ -2209,7 +2213,7 @@ static long do_unlinkat(int dfd, const char __user *pathname)
|
||||
error = -EISDIR;
|
||||
if (nd.last_type != LAST_NORM)
|
||||
goto exit1;
|
||||
mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
|
||||
dentry = lookup_hash(&nd);
|
||||
error = PTR_ERR(dentry);
|
||||
if (!IS_ERR(dentry)) {
|
||||
@@ -2219,11 +2223,11 @@ static long do_unlinkat(int dfd, const char __user *pathname)
|
||||
inode = dentry->d_inode;
|
||||
if (inode)
|
||||
atomic_inc(&inode->i_count);
|
||||
error = vfs_unlink(nd.dentry->d_inode, dentry);
|
||||
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
|
||||
exit2:
|
||||
dput(dentry);
|
||||
}
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
if (inode)
|
||||
iput(inode); /* truncate the inode here */
|
||||
exit1:
|
||||
@@ -2300,10 +2304,10 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
|
||||
if (IS_ERR(dentry))
|
||||
goto out_unlock;
|
||||
|
||||
error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
|
||||
error = vfs_symlink(nd.path.dentry->d_inode, dentry, from, S_IALLUGO);
|
||||
dput(dentry);
|
||||
out_unlock:
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
path_release(&nd);
|
||||
out:
|
||||
putname(to);
|
||||
@@ -2389,16 +2393,16 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
|
||||
if (error)
|
||||
goto out;
|
||||
error = -EXDEV;
|
||||
if (old_nd.mnt != nd.mnt)
|
||||
if (old_nd.path.mnt != nd.path.mnt)
|
||||
goto out_release;
|
||||
new_dentry = lookup_create(&nd, 0);
|
||||
error = PTR_ERR(new_dentry);
|
||||
if (IS_ERR(new_dentry))
|
||||
goto out_unlock;
|
||||
error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
|
||||
error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode, new_dentry);
|
||||
dput(new_dentry);
|
||||
out_unlock:
|
||||
mutex_unlock(&nd.dentry->d_inode->i_mutex);
|
||||
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
|
||||
out_release:
|
||||
path_release(&nd);
|
||||
out:
|
||||
@@ -2578,15 +2582,15 @@ static int do_rename(int olddfd, const char *oldname,
|
||||
goto exit1;
|
||||
|
||||
error = -EXDEV;
|
||||
if (oldnd.mnt != newnd.mnt)
|
||||
if (oldnd.path.mnt != newnd.path.mnt)
|
||||
goto exit2;
|
||||
|
||||
old_dir = oldnd.dentry;
|
||||
old_dir = oldnd.path.dentry;
|
||||
error = -EBUSY;
|
||||
if (oldnd.last_type != LAST_NORM)
|
||||
goto exit2;
|
||||
|
||||
new_dir = newnd.dentry;
|
||||
new_dir = newnd.path.dentry;
|
||||
if (newnd.last_type != LAST_NORM)
|
||||
goto exit2;
|
||||
|
||||
|
Reference in New Issue
Block a user