return err;
 }
 
-static inline struct dentry *__lookup_hash_kern(struct qstr *name, struct dentry *base, struct nameidata *nd)
+static struct dentry *__lookup_hash(struct qstr *name,
+               struct dentry *base, struct nameidata *nd)
 {
        struct dentry *dentry;
        struct inode *inode;
  * 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)
+static struct dentry *lookup_hash(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);
+       err = permission(nd->dentry->d_inode, MAY_EXEC, nd);
        if (err)
-               goto out;
-
-       dentry = __lookup_hash_kern(name, base, nd);
-out:
-       return dentry;
-}
-
-static struct dentry *lookup_hash(struct nameidata *nd)
-{
+               return ERR_PTR(err);
        return __lookup_hash(&nd->last, nd->dentry, nd);
 }
 
-/* SMP-safe */
-static inline int __lookup_one_len(const char *name, struct qstr *this, struct dentry *base, int len)
+static int __lookup_one_len(const char *name, struct qstr *this,
+               struct dentry *base, int len)
 {
        unsigned long hash;
        unsigned int c;
        return 0;
 }
 
+/**
+ * lookup_one_len:  filesystem helper to lookup single pathname component
+ * @name:      pathname component to lookup
+ * @base:      base directory to lookup from
+ * @len:       maximum length @len should be interpreted to
+ *
+ * Note that this routine is purely a helper for filesystem useage and should
+ * not be called by generic code.  Also note that by using this function to
+ * nameidata argument is passed to the filesystem methods and a filesystem
+ * using this helper needs to be prepared for that.
+ */
 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);
+
+       err = permission(base->d_inode, MAY_EXEC, NULL);
        if (err)
                return ERR_PTR(err);
        return __lookup_hash(&this, base, NULL);
 }
 
-struct dentry *lookup_one_len_kern(const char *name, struct dentry *base, int len)
+/**
+ * lookup_one_noperm - bad hack for sysfs
+ * @name:      pathname component to lookup
+ * @base:      base directory to lookup from
+ *
+ * This is a variant of lookup_one_len that doesn't perform any permission
+ * checks.   It's a horrible hack to work around the braindead sysfs
+ * architecture and should not be used anywhere else.
+ *
+ * DON'T USE THIS FUNCTION EVER, thanks.
+ */
+struct dentry *lookup_one_noperm(const char *name, struct dentry *base)
 {
        int err;
        struct qstr this;
 
-       err = __lookup_one_len(name, &this, base, len);
+       err = __lookup_one_len(name, &this, base, strlen(name));
        if (err)
                return ERR_PTR(err);
-       return __lookup_hash_kern(&this, base, NULL);
+       return __lookup_hash(&this, base, NULL);
 }
 
 int fastcall __user_walk_fd(int dfd, const char __user *name, unsigned flags,
 
 extern struct file *nameidata_to_filp(struct nameidata *nd, int flags);
 extern void release_open_intent(struct nameidata *);
 
-extern struct dentry * lookup_one_len(const char *, struct dentry *, int);
-extern struct dentry *lookup_one_len_kern(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_noperm(const char *, struct dentry *);
 
 extern int follow_down(struct vfsmount **, struct dentry **);
 extern int follow_up(struct vfsmount **, struct dentry **);