coda breakage
[safe/jmp/linux-2.6] / fs / namei.c
index 808e4ea..a83160a 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/quotaops.h>
 #include <linux/pagemap.h>
 #include <linux/fsnotify.h>
-#include <linux/smp_lock.h>
 #include <linux/personality.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
  * any extra contention...
  */
 
+static int fastcall 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
  * kernel data space before using them..
@@ -249,9 +250,11 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
 
        /*
         * MAY_EXEC on regular files requires special handling: We override
-        * filesystem execute permissions if the mode bits aren't set.
+        * filesystem execute permissions if the mode bits aren't set or
+        * the fs is mounted with the "noexec" flag.
         */
-       if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO))
+       if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) ||
+                       (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC))))
                return -EACCES;
 
        /* Ordinary permission routines do not understand MAY_APPEND. */
@@ -295,7 +298,7 @@ int vfs_permission(struct nameidata *nd, int mask)
  */
 int file_permission(struct file *file, int mask)
 {
-       return permission(file->f_dentry->d_inode, mask, NULL);
+       return permission(file->f_path.dentry->d_inode, mask, NULL);
 }
 
 /*
@@ -331,7 +334,7 @@ int get_write_access(struct inode * inode)
 
 int deny_write_access(struct file * file)
 {
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file->f_path.dentry->d_inode;
 
        spin_lock(&inode->i_lock);
        if (atomic_read(&inode->i_writecount) > 0) {
@@ -366,7 +369,7 @@ void path_release_on_umount(struct nameidata *nd)
  */
 void release_open_intent(struct nameidata *nd)
 {
-       if (nd->intent.open.file->f_dentry == NULL)
+       if (nd->intent.open.file->f_path.dentry == NULL)
                put_filp(nd->intent.open.file);
        else
                fput(nd->intent.open.file);
@@ -518,18 +521,20 @@ static int __emul_lookup_dentry(const char *, struct nameidata *);
 static __always_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);
+       struct fs_struct *fs = current->fs;
+
+       read_lock(&fs->lock);
+       if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+               nd->mnt = mntget(fs->altrootmnt);
+               nd->dentry = dget(fs->altroot);
+               read_unlock(&fs->lock);
                if (__emul_lookup_dentry(name,nd))
                        return 0;
-               read_lock(&current->fs->lock);
+               read_lock(&fs->lock);
        }
-       nd->mnt = mntget(current->fs->rootmnt);
-       nd->dentry = dget(current->fs->root);
-       read_unlock(&current->fs->lock);
+       nd->mnt = mntget(fs->rootmnt);
+       nd->dentry = dget(fs->root);
+       read_unlock(&fs->lock);
        return 1;
 }
 
@@ -568,11 +573,6 @@ fail:
        return PTR_ERR(link);
 }
 
-struct path {
-       struct vfsmount *mnt;
-       struct dentry *dentry;
-};
-
 static inline void dput_path(struct path *path, struct nameidata *nd)
 {
        dput(path->dentry);
@@ -724,17 +724,19 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
 
 static __always_inline void follow_dotdot(struct nameidata *nd)
 {
+       struct fs_struct *fs = current->fs;
+
        while(1) {
                struct vfsmount *parent;
                struct dentry *old = nd->dentry;
 
-                read_lock(&current->fs->lock);
-               if (nd->dentry == current->fs->root &&
-                   nd->mnt == current->fs->rootmnt) {
-                        read_unlock(&current->fs->lock);
+                read_lock(&fs->lock);
+               if (nd->dentry == fs->root &&
+                   nd->mnt == fs->rootmnt) {
+                        read_unlock(&fs->lock);
                        break;
                }
-                read_unlock(&current->fs->lock);
+                read_unlock(&fs->lock);
                spin_lock(&dcache_lock);
                if (nd->dentry != nd->mnt->mnt_root) {
                        nd->dentry = dget(nd->dentry->d_parent);
@@ -998,7 +1000,7 @@ return_err:
  * Retry the whole path once, forcing real lookup requests
  * instead of relying on the dcache.
  */
-int fastcall link_path_walk(const char *name, struct nameidata *nd)
+static int fastcall link_path_walk(const char *name, struct nameidata *nd)
 {
        struct nameidata save = *nd;
        int result;
@@ -1022,7 +1024,7 @@ int fastcall link_path_walk(const char *name, struct nameidata *nd)
        return result;
 }
 
-int fastcall path_walk(const char * name, struct nameidata *nd)
+static int fastcall path_walk(const char * name, struct nameidata *nd)
 {
        current->total_link_count = 0;
        return link_path_walk(name, nd);
@@ -1042,15 +1044,17 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
                struct vfsmount *old_mnt = nd->mnt;
                struct qstr last = nd->last;
                int last_type = nd->last_type;
+               struct fs_struct *fs = current->fs;
+
                /*
-                * NAME was not found in alternate root or it's a directory.  Try to find
-                * it in the normal root:
+                * NAME was not found in alternate root or it's a directory.
+                * Try to find it in the normal root:
                 */
                nd->last_type = LAST_ROOT;
-               read_lock(&current->fs->lock);
-               nd->mnt = mntget(current->fs->rootmnt);
-               nd->dentry = dget(current->fs->root);
-               read_unlock(&current->fs->lock);
+               read_lock(&fs->lock);
+               nd->mnt = mntget(fs->rootmnt);
+               nd->dentry = dget(fs->root);
+               read_unlock(&fs->lock);
                if (path_walk(name, nd) == 0) {
                        if (nd->dentry->d_inode) {
                                dput(old_dentry);
@@ -1074,6 +1078,7 @@ void set_fs_altroot(void)
        struct vfsmount *mnt = NULL, *oldmnt;
        struct dentry *dentry = NULL, *olddentry;
        int err;
+       struct fs_struct *fs = current->fs;
 
        if (!emul)
                goto set_it;
@@ -1083,12 +1088,12 @@ void set_fs_altroot(void)
                dentry = nd.dentry;
        }
 set_it:
-       write_lock(&current->fs->lock);
-       oldmnt = current->fs->altrootmnt;
-       olddentry = current->fs->altroot;
-       current->fs->altrootmnt = mnt;
-       current->fs->altroot = dentry;
-       write_unlock(&current->fs->lock);
+       write_lock(&fs->lock);
+       oldmnt = fs->altrootmnt;
+       olddentry = fs->altroot;
+       fs->altrootmnt = mnt;
+       fs->altroot = dentry;
+       write_unlock(&fs->lock);
        if (olddentry) {
                dput(olddentry);
                mntput(oldmnt);
@@ -1102,29 +1107,30 @@ static int fastcall do_path_lookup(int dfd, const char *name,
        int retval = 0;
        int fput_needed;
        struct file *file;
+       struct fs_struct *fs = current->fs;
 
        nd->last_type = LAST_ROOT; /* if there are only slashes... */
        nd->flags = flags;
        nd->depth = 0;
 
        if (*name=='/') {
-               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);
+               read_lock(&fs->lock);
+               if (fs->altroot && !(nd->flags & LOOKUP_NOALT)) {
+                       nd->mnt = mntget(fs->altrootmnt);
+                       nd->dentry = dget(fs->altroot);
+                       read_unlock(&fs->lock);
                        if (__emul_lookup_dentry(name,nd))
                                goto out; /* found in altroot */
-                       read_lock(&current->fs->lock);
+                       read_lock(&fs->lock);
                }
-               nd->mnt = mntget(current->fs->rootmnt);
-               nd->dentry = dget(current->fs->root);
-               read_unlock(&current->fs->lock);
+               nd->mnt = mntget(fs->rootmnt);
+               nd->dentry = dget(fs->root);
+               read_unlock(&fs->lock);
        } else if (dfd == AT_FDCWD) {
-               read_lock(&current->fs->lock);
-               nd->mnt = mntget(current->fs->pwdmnt);
-               nd->dentry = dget(current->fs->pwd);
-               read_unlock(&current->fs->lock);
+               read_lock(&fs->lock);
+               nd->mnt = mntget(fs->pwdmnt);
+               nd->dentry = dget(fs->pwd);
+               read_unlock(&fs->lock);
        } else {
                struct dentry *dentry;
 
@@ -1133,7 +1139,7 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (!file)
                        goto out_fail;
 
-               dentry = file->f_dentry;
+               dentry = file->f_path.dentry;
 
                retval = -ENOTDIR;
                if (!S_ISDIR(dentry->d_inode->i_mode))
@@ -1143,19 +1149,17 @@ static int fastcall do_path_lookup(int dfd, const char *name,
                if (retval)
                        goto fput_fail;
 
-               nd->mnt = mntget(file->f_vfsmnt);
+               nd->mnt = mntget(file->f_path.mnt);
                nd->dentry = dget(dentry);
 
                fput_light(file, fput_needed);
        }
-       current->total_link_count = 0;
-       retval = link_path_walk(name, nd);
+
+       retval = path_walk(name, nd);
 out:
-       if (likely(retval == 0)) {
-               if (unlikely(!audit_dummy_context() && nd && nd->dentry &&
+       if (unlikely(!retval && !audit_dummy_context() && nd->dentry &&
                                nd->dentry->d_inode))
                audit_inode(name, nd->dentry->d_inode);
-       }
 out_fail:
        return retval;
 
@@ -1170,6 +1174,37 @@ int fastcall path_lookup(const char *name, unsigned int flags,
        return do_path_lookup(AT_FDCWD, name, flags, nd);
 }
 
+/**
+ * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair
+ * @dentry:  pointer to dentry of the base directory
+ * @mnt: pointer to vfs mount of the base directory
+ * @name: pointer to file name
+ * @flags: lookup flags
+ * @nd: pointer to nameidata
+ */
+int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
+                   const char *name, unsigned int flags,
+                   struct nameidata *nd)
+{
+       int retval;
+
+       /* same as do_path_lookup */
+       nd->last_type = LAST_ROOT;
+       nd->flags = flags;
+       nd->depth = 0;
+
+       nd->mnt = mntget(mnt);
+       nd->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->d_inode);
+
+       return retval;
+
+}
+
 static int __path_lookup_intent_open(int dfd, const char *name,
                unsigned int lookup_flags, struct nameidata *nd,
                int open_flags, int create_mode)
@@ -1238,22 +1273,13 @@ int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
        return err;
 }
 
-/*
- * Restricted form of lookup. Doesn't follow links, single-component only,
- * needs parent already locked. Doesn't follow mounts.
- * SMP-safe.
- */
-static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
+static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
 {
-       struct dentry * dentry;
+       struct dentry *dentry;
        struct inode *inode;
        int err;
 
        inode = base->d_inode;
-       err = permission(inode, MAY_EXEC, nd);
-       dentry = ERR_PTR(err);
-       if (err)
-               goto out;
 
        /*
         * See if the low-level filesystem might want
@@ -1282,48 +1308,78 @@ out:
        return dentry;
 }
 
+/*
+ * Restricted form of lookup. Doesn't follow links, single-component only,
+ * needs parent already locked. Doesn't follow mounts.
+ * SMP-safe.
+ */
+static inline struct dentry * __lookup_hash(struct qstr *name, struct dentry *base, struct nameidata *nd)
+{
+       struct dentry *dentry;
+       struct inode *inode;
+       int err;
+
+       inode = base->d_inode;
+
+       err = permission(inode, MAY_EXEC, nd);
+       dentry = ERR_PTR(err);
+       if (err)
+               goto out;
+
+       dentry = __lookup_hash_kern(name, base, nd);
+out:
+       return dentry;
+}
+
 static struct dentry *lookup_hash(struct nameidata *nd)
 {
        return __lookup_hash(&nd->last, nd->dentry, nd);
 }
 
 /* SMP-safe */
-struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
+static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
 {
        unsigned long hash;
-       struct qstr this;
        unsigned int c;
 
-       this.name = name;
-       this.len = len;
+       this->name = name;
+       this->len = len;
        if (!len)
-               goto access;
+               return -EACCES;
 
        hash = init_name_hash();
        while (len--) {
                c = *(const unsigned char *)name++;
                if (c == '/' || c == '\0')
-                       goto access;
+                       return -EACCES;
                hash = partial_name_hash(c, hash);
        }
-       this.hash = end_name_hash(hash);
+       this->hash = end_name_hash(hash);
+       return 0;
+}
 
+struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
+{
+       int err;
+       struct qstr this;
+
+       err = __lookup_one_len(name, &this, base, len);
+       if (err)
+               return ERR_PTR(err);
        return __lookup_hash(&this, base, NULL);
-access:
-       return ERR_PTR(-EACCES);
 }
 
-/*
- *     namei()
- *
- * is used by most simple commands to get the inode of a specified name.
- * Open, link etc use their own routines, but this is enough for things
- * like 'chmod' etc.
- *
- * namei exists in two versions: namei/lnamei. The only difference is
- * that namei follows links, while lnamei does not.
- * SMP-safe
- */
+struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
+{
+       int err;
+       struct qstr this;
+
+       err = __lookup_one_len(name, &this, base, len);
+       if (err)
+               return ERR_PTR(err);
+       return __lookup_hash_kern(&this, base, NULL);
+}
+
 int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
                            struct nameidata *nd)
 {
@@ -1553,7 +1609,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
 
        /* O_NOATIME can only be set by the owner or superuser */
        if (flag & O_NOATIME)
-               if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
+               if (!is_owner_or_cap(inode))
                        return -EPERM;
 
        /*
@@ -1587,6 +1643,24 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
        return 0;
 }
 
+static int open_namei_create(struct nameidata *nd, struct path *path,
+                               int flag, int mode)
+{
+       int error;
+       struct dentry *dir = nd->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;
+       if (error)
+               return error;
+       /* Don't check for write permission, don't truncate */
+       return may_open(nd, 0, flag & ~O_TRUNC);
+}
+
 /*
  *     open_namei()
  *
@@ -1668,25 +1742,17 @@ do_last:
 
        /* Negative dentry, just create the file */
        if (!path.dentry->d_inode) {
-               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;
+               error = open_namei_create(nd, &path, flag, mode);
                if (error)
                        goto exit;
-               /* Don't check for write permission, don't truncate */
-               acc_mode = 0;
-               flag &= ~O_TRUNC;
-               goto ok;
+               return 0;
        }
 
        /*
         * It already exists.
         */
        mutex_unlock(&dir->d_inode->i_mutex);
-       audit_inode_update(path.dentry->d_inode);
+       audit_inode(pathname, path.dentry->d_inode);
 
        error = -EEXIST;
        if (flag & O_EXCL)
@@ -1926,30 +1992,32 @@ asmlinkage long sys_mkdirat(int dfd, const char __user *pathname, int mode)
 {
        int error = 0;
        char * tmp;
+       struct dentry *dentry;
+       struct nameidata nd;
 
        tmp = getname(pathname);
        error = PTR_ERR(tmp);
-       if (!IS_ERR(tmp)) {
-               struct dentry *dentry;
-               struct nameidata nd;
+       if (IS_ERR(tmp))
+               goto out_err;
 
-               error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
-               if (error)
-                       goto out;
-               dentry = lookup_create(&nd, 1);
-               error = PTR_ERR(dentry);
-               if (!IS_ERR(dentry)) {
-                       if (!IS_POSIXACL(nd.dentry->d_inode))
-                               mode &= ~current->fs->umask;
-                       error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
-                       dput(dentry);
-               }
-               mutex_unlock(&nd.dentry->d_inode->i_mutex);
-               path_release(&nd);
-out:
-               putname(tmp);
-       }
+       error = do_path_lookup(dfd, tmp, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
+       dentry = lookup_create(&nd, 1);
+       error = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
+               goto out_unlock;
 
+       if (!IS_POSIXACL(nd.dentry->d_inode))
+               mode &= ~current->fs->umask;
+       error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
+       dput(dentry);
+out_unlock:
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
+       path_release(&nd);
+out:
+       putname(tmp);
+out_err:
        return error;
 }
 
@@ -1976,8 +2044,7 @@ asmlinkage long sys_mkdir(const char __user *pathname, int mode)
 void dentry_unhash(struct dentry *dentry)
 {
        dget(dentry);
-       if (atomic_read(&dentry->d_count))
-               shrink_dcache_parent(dentry);
+       shrink_dcache_parent(dentry);
        spin_lock(&dcache_lock);
        spin_lock(&dentry->d_lock);
        if (atomic_read(&dentry->d_count) == 2)
@@ -2048,10 +2115,11 @@ static long do_rmdir(int dfd, const char __user *pathname)
        mutex_lock_nested(&nd.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
        dentry = lookup_hash(&nd);
        error = PTR_ERR(dentry);
-       if (!IS_ERR(dentry)) {
-               error = vfs_rmdir(nd.dentry->d_inode, dentry);
-               dput(dentry);
-       }
+       if (IS_ERR(dentry))
+               goto exit2;
+       error = vfs_rmdir(nd.dentry->d_inode, dentry);
+       dput(dentry);
+exit2:
        mutex_unlock(&nd.dentry->d_inode->i_mutex);
 exit1:
        path_release(&nd);
@@ -2191,30 +2259,33 @@ asmlinkage long sys_symlinkat(const char __user *oldname,
        int error = 0;
        char * from;
        char * to;
+       struct dentry *dentry;
+       struct nameidata nd;
 
        from = getname(oldname);
        if(IS_ERR(from))
                return PTR_ERR(from);
        to = getname(newname);
        error = PTR_ERR(to);
-       if (!IS_ERR(to)) {
-               struct dentry *dentry;
-               struct nameidata nd;
+       if (IS_ERR(to))
+               goto out_putname;
 
-               error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
-               if (error)
-                       goto out;
-               dentry = lookup_create(&nd, 0);
-               error = PTR_ERR(dentry);
-               if (!IS_ERR(dentry)) {
-                       error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
-                       dput(dentry);
-               }
-               mutex_unlock(&nd.dentry->d_inode->i_mutex);
-               path_release(&nd);
+       error = do_path_lookup(newdfd, to, LOOKUP_PARENT, &nd);
+       if (error)
+               goto out;
+       dentry = lookup_create(&nd, 0);
+       error = PTR_ERR(dentry);
+       if (IS_ERR(dentry))
+               goto out_unlock;
+
+       error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
+       dput(dentry);
+out_unlock:
+       mutex_unlock(&nd.dentry->d_inode->i_mutex);
+       path_release(&nd);
 out:
-               putname(to);
-       }
+       putname(to);
+out_putname:
        putname(from);
        return error;
 }
@@ -2300,10 +2371,11 @@ asmlinkage long sys_linkat(int olddfd, const char __user *oldname,
                goto out_release;
        new_dentry = lookup_create(&nd, 0);
        error = PTR_ERR(new_dentry);
-       if (!IS_ERR(new_dentry)) {
-               error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
-               dput(new_dentry);
-       }
+       if (IS_ERR(new_dentry))
+               goto out_unlock;
+       error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
+       dput(new_dentry);
+out_unlock:
        mutex_unlock(&nd.dentry->d_inode->i_mutex);
 out_release:
        path_release(&nd);
@@ -2618,19 +2690,9 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage)
        struct address_space *mapping = dentry->d_inode->i_mapping;
        page = read_mapping_page(mapping, 0, NULL);
        if (IS_ERR(page))
-               goto sync_fail;
-       wait_on_page_locked(page);
-       if (!PageUptodate(page))
-               goto async_fail;
+               return (char*)page;
        *ppage = page;
        return kmap(page);
-
-async_fail:
-       page_cache_release(page);
-       return ERR_PTR(-EIO);
-
-sync_fail:
-       return (char*)page;
 }
 
 int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
@@ -2667,10 +2729,11 @@ int __page_symlink(struct inode *inode, const char *symname, int len,
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
-       int err = -ENOMEM;
+       int err;
        char *kaddr;
 
 retry:
+       err = -ENOMEM;
        page = find_or_create_page(mapping, 0, gfp_mask);
        if (!page)
                goto fail;
@@ -2723,7 +2786,7 @@ int page_symlink(struct inode *inode, const char *symname, int len)
                        mapping_gfp_mask(inode->i_mapping));
 }
 
-struct inode_operations page_symlink_inode_operations = {
+const struct inode_operations page_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .follow_link    = page_follow_link_light,
        .put_link       = page_put_link,
@@ -2744,8 +2807,8 @@ EXPORT_SYMBOL(__page_symlink);
 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(path_walk);
 EXPORT_SYMBOL(permission);
 EXPORT_SYMBOL(vfs_permission);
 EXPORT_SYMBOL(file_permission);