From 56ea78c1648b923022636d554da1bf028d373d5e Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Sat, 30 Apr 2011 01:33:58 -0400 Subject: [PATCH] VFS: introduce lookup_one_len_nd 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 --- fs/namei.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/namei.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/fs/namei.c b/fs/namei.c index 399f6378de5..ccb1b7e93fe 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2101,6 +2101,42 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) return __lookup_hash(&this, base, 0); } +/* 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) { @@ -4405,6 +4441,7 @@ EXPORT_SYMBOL(follow_up); EXPORT_SYMBOL(get_write_access); /* nfsd */ 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); diff --git a/include/linux/namei.h b/include/linux/namei.h index 492de72560f..34fbc2d3396 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -73,6 +73,8 @@ extern struct dentry *kern_path_locked(const char *, struct path *); extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int); 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 *); -- 2.34.1