VFS: introduce lookup_one_len_nd
authorErez Zadok <ezk@cs.sunysb.edu>
Sat, 30 Apr 2011 05:33:58 +0000 (01:33 -0400)
committerErez Zadok <ezk@cs.sunysb.edu>
Sat, 23 Nov 2013 01:09:11 +0000 (20:09 -0500)
Just like lookup_one_len() but passes a nameidata parameter, which is now
required by NFS3, else you get an oops.

Signed-off-by: Erez Zadok <ezk@cs.sunysb.edu>
fs/namei.c
include/linux/namei.h

index 8cfa6395c6d55057be6862dd964754a32dbd36d4..a60be8110e7c14fd97a803e8be619a7528c892c0 100644 (file)
@@ -1829,6 +1829,42 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        return __lookup_hash(&this, base, NULL);
 }
 
+/* pass nameidata from caller (useful for NFS) */
+struct dentry *lookup_one_len_nd(const char *name, struct dentry *base,
+                                int len, struct nameidata *nd)
+{
+       struct qstr this;
+       unsigned long hash;
+       unsigned int c;
+
+       WARN_ON_ONCE(!mutex_is_locked(&base->d_inode->i_mutex));
+
+       this.name = name;
+       this.len = len;
+       if (!len)
+               return ERR_PTR(-EACCES);
+
+       hash = init_name_hash();
+       while (len--) {
+               c = *(const unsigned char *)name++;
+               if (c == '/' || c == '\0')
+                       return ERR_PTR(-EACCES);
+               hash = partial_name_hash(c, hash);
+       }
+       this.hash = end_name_hash(hash);
+       /*
+        * See if the low-level filesystem might want
+        * to use its own hash..
+        */
+       if (base->d_flags & DCACHE_OP_HASH) {
+               int err = base->d_op->d_hash(base, base->d_inode, &this);
+               if (err < 0)
+                       return ERR_PTR(err);
+       }
+
+       return __lookup_hash(&this, base, nd);
+}
+
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
                 struct path *path, int *empty)
 {
@@ -3409,6 +3445,7 @@ EXPORT_SYMBOL(get_write_access); /* binfmt_aout */
 EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
 EXPORT_SYMBOL(lookup_one_len);
+EXPORT_SYMBOL(lookup_one_len_nd);
 EXPORT_SYMBOL(page_follow_link_light);
 EXPORT_SYMBOL(page_put_link);
 EXPORT_SYMBOL(page_readlink);
index 7d7dfab764f5d1d31e1555f460e0736f8dfa04b3..99802c38dd287232c414a678c5312b734297f4a3 100644 (file)
@@ -87,6 +87,8 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry
 extern void release_open_intent(struct nameidata *);
 
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
+extern struct dentry *lookup_one_len_nd(const char *, struct dentry *, int,
+                                     struct nameidata *nd);
 
 extern int follow_down_one(struct path *);
 extern int follow_down(struct path *);