diff options
author | Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu> | 2007-07-19 04:48:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 13:04:45 -0400 |
commit | 16f1820028d660d9da9c03b2ae7e98253c11795b (patch) | |
tree | 08939a5d7fcc02c76739a9dce38052da598d74d5 | |
parent | b6a2fea39318e43fee84fa7b0b90d68bed92d2ba (diff) |
fs: introduce vfs_path_lookup
Stackable file systems, among others, frequently need to lookup paths or
path components starting from an arbitrary point in the namespace
(identified by a dentry and a vfsmount). Currently, such file systems use
lookup_one_len, which is frowned upon [1] as it does not pass the lookup
intent along; not passing a lookup intent, for example, can trigger BUG_ON's
when stacking on top of NFSv4.
The first patch introduces a new lookup function to allow lookup starting
from an arbitrary point in the namespace. This approach has been suggested
by Christoph Hellwig [2].
The second patch changes sunrpc to use vfs_path_lookup.
The third patch changes nfsctl.c to use vfs_path_lookup.
The fourth patch marks link_path_walk static.
The fifth, and last patch, unexports path_walk because it is no longer
unnecessary to call it directly, and using the new vfs_path_lookup is
cleaner.
For example, the following snippet of code, looks up "some/path/component"
in a directory pointed to by parent_{dentry,vfsmnt}:
err = vfs_path_lookup(parent_dentry, parent_vfsmnt,
"some/path/component", 0, &nd);
if (!err) {
/* exits */
...
/* once done, release the references */
path_release(&nd);
} else if (err == -ENOENT) {
/* doesn't exist */
} else {
/* other error */
}
VFS functions such as lookup_create can be used on the nameidata structure
to pass the create intent to the file system.
Signed-off-by: Josef 'Jeff' Sipek <jsipek@cs.sunysb.edu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Christoph Hellwig <hch@lst.de>
Cc: Trond Myklebust <trond.myklebust@fys.uio.no>
Cc: Neil Brown <neilb@suse.de>
Cc: Michael Halcrow <mhalcrow@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/namei.c | 32 | ||||
-rw-r--r-- | include/linux/namei.h | 2 |
2 files changed, 34 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c index defaa47c11d4..3bdb29615a9d 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1172,6 +1172,37 @@ int fastcall path_lookup(const char *name, unsigned int flags, | |||
1172 | return do_path_lookup(AT_FDCWD, name, flags, nd); | 1172 | return do_path_lookup(AT_FDCWD, name, flags, nd); |
1173 | } | 1173 | } |
1174 | 1174 | ||
1175 | /** | ||
1176 | * vfs_path_lookup - lookup a file path relative to a dentry-vfsmount pair | ||
1177 | * @dentry: pointer to dentry of the base directory | ||
1178 | * @mnt: pointer to vfs mount of the base directory | ||
1179 | * @name: pointer to file name | ||
1180 | * @flags: lookup flags | ||
1181 | * @nd: pointer to nameidata | ||
1182 | */ | ||
1183 | int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt, | ||
1184 | const char *name, unsigned int flags, | ||
1185 | struct nameidata *nd) | ||
1186 | { | ||
1187 | int retval; | ||
1188 | |||
1189 | /* same as do_path_lookup */ | ||
1190 | nd->last_type = LAST_ROOT; | ||
1191 | nd->flags = flags; | ||
1192 | nd->depth = 0; | ||
1193 | |||
1194 | nd->mnt = mntget(mnt); | ||
1195 | nd->dentry = dget(dentry); | ||
1196 | |||
1197 | retval = path_walk(name, nd); | ||
1198 | if (unlikely(!retval && !audit_dummy_context() && nd->dentry && | ||
1199 | nd->dentry->d_inode)) | ||
1200 | audit_inode(name, nd->dentry->d_inode); | ||
1201 | |||
1202 | return retval; | ||
1203 | |||
1204 | } | ||
1205 | |||
1175 | static int __path_lookup_intent_open(int dfd, const char *name, | 1206 | static int __path_lookup_intent_open(int dfd, const char *name, |
1176 | unsigned int lookup_flags, struct nameidata *nd, | 1207 | unsigned int lookup_flags, struct nameidata *nd, |
1177 | int open_flags, int create_mode) | 1208 | int open_flags, int create_mode) |
@@ -2774,6 +2805,7 @@ EXPORT_SYMBOL(__page_symlink); | |||
2774 | EXPORT_SYMBOL(page_symlink); | 2805 | EXPORT_SYMBOL(page_symlink); |
2775 | EXPORT_SYMBOL(page_symlink_inode_operations); | 2806 | EXPORT_SYMBOL(page_symlink_inode_operations); |
2776 | EXPORT_SYMBOL(path_lookup); | 2807 | EXPORT_SYMBOL(path_lookup); |
2808 | EXPORT_SYMBOL(vfs_path_lookup); | ||
2777 | EXPORT_SYMBOL(path_release); | 2809 | EXPORT_SYMBOL(path_release); |
2778 | EXPORT_SYMBOL(path_walk); | 2810 | EXPORT_SYMBOL(path_walk); |
2779 | EXPORT_SYMBOL(permission); | 2811 | EXPORT_SYMBOL(permission); |
diff --git a/include/linux/namei.h b/include/linux/namei.h index b7dd24917f0d..2e21af0989d9 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
@@ -69,6 +69,8 @@ extern int FASTCALL(__user_walk_fd(int dfd, const char __user *, unsigned, struc | |||
69 | #define user_path_walk_link(name,nd) \ | 69 | #define user_path_walk_link(name,nd) \ |
70 | __user_walk_fd(AT_FDCWD, name, 0, nd) | 70 | __user_walk_fd(AT_FDCWD, name, 0, nd) |
71 | extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); | 71 | extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *)); |
72 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | ||
73 | const char *, unsigned int, struct nameidata *); | ||
72 | extern int FASTCALL(path_walk(const char *, struct nameidata *)); | 74 | extern int FASTCALL(path_walk(const char *, struct nameidata *)); |
73 | extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); | 75 | extern int FASTCALL(link_path_walk(const char *, struct nameidata *)); |
74 | extern void path_release(struct nameidata *); | 76 | extern void path_release(struct nameidata *); |