Use path_put() in a few places instead of {mnt,d}put()
[pandora-kernel.git] / fs / namei.c
index 241cff4..0249935 100644 (file)
  * any extra contention...
  */
 
-static int fastcall link_path_walk(const char *name, struct nameidata *nd);
+static int link_path_walk(const char *name, struct nameidata *nd);
 
 /* In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
@@ -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);
 }
 
 /**
@@ -362,21 +362,18 @@ int deny_write_access(struct file * file)
        return 0;
 }
 
-void path_release(struct nameidata *nd)
-{
-       dput(nd->dentry);
-       mntput(nd->mnt);
-}
-
-/*
- * umount() mustn't call path_release()/mntput() as that would clear
- * mnt_expiry_mark
+/**
+ * path_put - put a reference to a path
+ * @path: path to put the reference to
+ *
+ * Given a path decrement the reference count to the dentry and the vfsmount.
  */
-void path_release_on_umount(struct nameidata *nd)
+void path_put(struct path *path)
 {
-       dput(nd->dentry);
-       mntput_no_expire(nd->mnt);
+       dput(path->dentry);
+       mntput(path->mnt);
 }
+EXPORT_SYMBOL(path_put);
 
 /**
  * release_open_intent - free up open intent resources
@@ -540,15 +537,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;
 }
@@ -561,7 +558,7 @@ static __always_inline int __vfs_follow_link(struct nameidata *nd, const char *l
                goto fail;
 
        if (*link == '/') {
-               path_release(nd);
+               path_put(&nd->path);
                if (!walk_init_root(link, nd))
                        /* weird __emul_prefix() stuff did it */
                        goto out;
@@ -577,31 +574,31 @@ out:
         */
        name = __getname();
        if (unlikely(!name)) {
-               path_release(nd);
+               path_put(&nd->path);
                return -ENOMEM;
        }
        strcpy(name, nd->last.name);
        nd->last.name = name;
        return 0;
 fail:
-       path_release(nd);
+       path_put(&nd->path);
        return PTR_ERR(link);
 }
 
-static inline void dput_path(struct path *path, struct nameidata *nd)
+static void path_put_conditional(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)
@@ -613,7 +610,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);
        }
@@ -628,8 +625,7 @@ static __always_inline int __do_follow_link(struct path *path, struct nameidata
                if (dentry->d_inode->i_op->put_link)
                        dentry->d_inode->i_op->put_link(dentry, nd, cookie);
        }
-       dput(dentry);
-       mntput(path->mnt);
+       path_put(path);
 
        return error;
 }
@@ -661,8 +657,8 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd)
        nd->depth--;
        return err;
 loop:
-       dput_path(path, nd);
-       path_release(nd);
+       path_put_conditional(path, nd);
+       path_put(&nd->path);
        return err;
 }
 
@@ -743,37 +739,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);
 }
 
 /*
@@ -784,8 +780,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;
@@ -798,7 +794,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;
@@ -823,7 +819,7 @@ fail:
  * Returns 0 and nd will have valid dentry and mnt on success.
  * Returns error and drops reference to input namei data on failure.
  */
-static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
+static int __link_path_walk(const char *name, struct nameidata *nd)
 {
        struct path next;
        struct inode *inode;
@@ -835,7 +831,7 @@ static fastcall 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);
 
@@ -883,7 +879,7 @@ static fastcall 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;
@@ -892,8 +888,9 @@ static fastcall 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;
                }
@@ -915,7 +912,7 @@ static fastcall 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; 
@@ -943,13 +940,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;
                }
@@ -962,7 +960,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;
@@ -990,20 +988,21 @@ 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:
                return 0;
 out_dput:
-               dput_path(&next, nd);
+               path_put_conditional(&next, nd);
                break;
        }
-       path_release(nd);
+       path_put(&nd->path);
 return_err:
        return err;
 }
@@ -1015,31 +1014,30 @@ return_err:
  * Retry the whole path once, forcing real lookup requests
  * instead of relying on the dcache.
  */
-static int fastcall link_path_walk(const char *name, struct nameidata *nd)
+static int link_path_walk(const char *name, struct nameidata *nd)
 {
        struct nameidata save = *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);
+       path_put(&save.path);
 
        return result;
 }
 
-static int fastcall path_walk(const char * name, struct nameidata *nd)
+static int path_walk(const char *name, struct nameidata *nd)
 {
        current->total_link_count = 0;
        return link_path_walk(name, nd);
@@ -1054,9 +1052,9 @@ 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 path old_path = nd->path;
                struct qstr last = nd->last;
                int last_type = nd->last_type;
                struct fs_struct *fs = current->fs;
@@ -1067,19 +1065,17 @@ 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) {
-                               dput(old_dentry);
-                               mntput(old_mnt);
+                       if (nd->path.dentry->d_inode) {
+                               path_put(&old_path);
                                return 1;
                        }
-                       path_release(nd);
+                       path_put(&nd->path);
                }
-               nd->dentry = old_dentry;
-               nd->mnt = old_mnt;
+               nd->path = old_path;
                nd->last = last;
                nd->last_type = last_type;
        }
@@ -1099,8 +1095,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);
@@ -1116,7 +1112,7 @@ set_it:
 }
 
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
-static int fastcall do_path_lookup(int dfd, const char *name,
+static int do_path_lookup(int dfd, const char *name,
                                unsigned int flags, struct nameidata *nd)
 {
        int retval = 0;
@@ -1131,20 +1127,20 @@ static int fastcall 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;
@@ -1164,17 +1160,17 @@ static int fastcall 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;
 
@@ -1183,7 +1179,7 @@ fput_fail:
        goto out_fail;
 }
 
-int fastcall path_lookup(const char *name, unsigned int flags,
+int path_lookup(const char *name, unsigned int flags,
                        struct nameidata *nd)
 {
        return do_path_lookup(AT_FDCWD, name, flags, nd);
@@ -1208,13 +1204,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;
 
@@ -1236,7 +1232,7 @@ static int __path_lookup_intent_open(int dfd, const char *name,
        if (IS_ERR(nd->intent.open.file)) {
                if (err == 0) {
                        err = PTR_ERR(nd->intent.open.file);
-                       path_release(nd);
+                       path_put(&nd->path);
                }
        } else if (err != 0)
                release_open_intent(nd);
@@ -1333,10 +1329,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,
@@ -1409,7 +1405,7 @@ struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
        return __lookup_hash(&this, base, NULL);
 }
 
-int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
+int __user_walk_fd(int dfd, const char __user *name, unsigned flags,
                            struct nameidata *nd)
 {
        char *tmp = getname(name);
@@ -1422,7 +1418,7 @@ int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
        return err;
 }
 
-int fastcall __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
+int __user_walk(const char __user *name, unsigned flags, struct nameidata *nd)
 {
        return __user_walk_fd(AT_FDCWD, name, flags, nd);
 }
@@ -1595,7 +1591,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;
 
@@ -1616,7 +1612,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;
@@ -1678,14 +1674,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 */
@@ -1752,11 +1748,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);
@@ -1812,11 +1808,11 @@ ok:
        return 0;
 
 exit_dput:
-       dput_path(&path, nd);
+       path_put_conditional(&path, nd);
 exit:
        if (!IS_ERR(nd->intent.open.file))
                release_open_intent(nd);
-       path_release(nd);
+       path_put(&nd->path);
        return error;
 
 do_link:
@@ -1861,10 +1857,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;
 }
@@ -1877,13 +1873,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/.., /////)
@@ -1962,19 +1958,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;
@@ -1984,8 +1980,8 @@ asmlinkage long sys_mknodat(int dfd, const char __user *filename, int mode,
                }
                dput(dentry);
        }
-       mutex_unlock(&nd.dentry->d_inode->i_mutex);
-       path_release(&nd);
+       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       path_put(&nd.path);
 out:
        putname(tmp);
 
@@ -2039,13 +2035,13 @@ 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);
-       path_release(&nd);
+       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       path_put(&nd.path);
 out:
        putname(tmp);
 out_err:
@@ -2143,17 +2139,17 @@ 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);
+       path_put(&nd.path);
 exit:
        putname(name);
        return error;
@@ -2219,7 +2215,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)) {
@@ -2229,15 +2225,15 @@ 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:
-       path_release(&nd);
+       path_put(&nd.path);
 exit:
        putname(name);
        return error;
@@ -2310,11 +2306,11 @@ 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);
-       path_release(&nd);
+       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       path_put(&nd.path);
 out:
        putname(to);
 out_putname:
@@ -2399,20 +2395,20 @@ 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);
+       path_put(&nd.path);
 out:
-       path_release(&old_nd);
+       path_put(&old_nd.path);
 exit:
        putname(to);
 
@@ -2588,15 +2584,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;
 
@@ -2640,9 +2636,9 @@ exit4:
 exit3:
        unlock_rename(new_dir, old_dir);
 exit2:
-       path_release(&newnd);
+       path_put(&newnd.path);
 exit1:
-       path_release(&oldnd);
+       path_put(&oldnd.path);
 exit:
        return error;
 }
@@ -2816,7 +2812,6 @@ EXPORT_SYMBOL(page_symlink);
 EXPORT_SYMBOL(page_symlink_inode_operations);
 EXPORT_SYMBOL(path_lookup);
 EXPORT_SYMBOL(vfs_path_lookup);
-EXPORT_SYMBOL(path_release);
 EXPORT_SYMBOL(permission);
 EXPORT_SYMBOL(vfs_permission);
 EXPORT_SYMBOL(file_permission);