Skip to contentSkip to conversation

path_lookup - simple precursor to fast_walk

PATCH New Hanna Linder 1 participant 1 message Mar 26, 2002

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 path_lookup - simple precursor to fast_walk

This is a cleanup precursor to a fast_walk patch I wrote based on suggestions from Al Viro to decrease cacheline bouncing of a global reference counter during path lookup of dentries in the cache. That patch has shown 50% reduction in BKL contention on an 8-way SMP running dbench. Incidentally, it has also shown a 90% reduction in dcache_lock contention on a 16-way NUMA-Q building the kernel. Results and patch coming soon.

This patch included simply cleans up source code by changing the many calls of the form: if(path_init) error = path_walk to one function path_lookup. By wrapping path_init with path_lookup I will be able to control which filesystems use the fast_walk mechanism.

Linus has already accepted this patch from Al Viro in 2.5.6, his comments:
<[email protected]> (02/03/02 1.375.1.84)
[PATCH] path_lookup()

New helper:
path_lookup(name, flags, nd)
{
int err = 0;
if (path_init(name, flags, nd))
err = path_walk(name, nd);
return err;
}

Places doing that by hand converted to calling it.

Actually, quite a few of them were doing equivalent of __user_walk() (getname() and if it was successful - call path_lookup() and putname()). Converted to calling __user_walk().

Please consider this patch for inclusion in your 2.4.19 tree.

Following is the linux-2.4.19-pre3-ac6 version. Also available at:
http://prdownloads.sf.net/lse/path_lookupA3-2.4.19-pre3-ac6.patch

Hanna Linder
[email protected]
IBM Linux Technology Center

--------

fs/exec.c +1 -2
diff -Nru -X dontdiff linux-2.4.19-pre3-ac6/fs/exec.c linux-path_lookup/fs/exec.c
@@ -351,8 +351,7 @@
 	struct file *file;
 	int err = 0;
 
-	if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
-		err = path_walk(name, &nd);
+	err = path_lookup(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
 	file = ERR_PTR(err);
 	if (!err) {
 		inode = nd.dentry->d_inode;
fs/namei.c +22 -32

139 lines not on this page · raw message

fs/namespace.c +6 -32
diff -Nru -X dontdiff linux-2.4.19-pre3-ac6/fs/namespace.c linux-path_lookup/fs/namespace.c
@@ -364,17 +364,9 @@
 asmlinkage long sys_umount(char * name, int flags)
 {
 	struct nameidata nd;
-	char *kname;
 	int retval;
 
-	kname = getname(name);
-	retval = PTR_ERR(kname);
-	if (IS_ERR(kname))
-		goto out;
-	retval = 0;
-	if (path_init(kname, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd))
-		retval = path_walk(kname, &nd);
-	putname(kname);
+	retval = __user_walk(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd);
 	if (retval)
 		goto out;
 	retval = -EINVAL;
@@ -501,8 +493,7 @@
 		return err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
-	if (path_init(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd))
-		err = path_walk(old_name, &old_nd);
+	err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
 	if (err)
 		return err;
 
@@ -568,8 +559,7 @@
 		return -EPERM;
 	if (!old_name || !*old_name)
 		return -EINVAL;
-	if (path_init(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd))
-		err = path_walk(old_name, &old_nd);
+	err = path_lookup(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd);
 	if (err)
 		return err;
 
@@ -726,8 +716,7 @@
 	flags &= ~(MS_NOSUID|MS_NOEXEC|MS_NODEV);
 
 	/* ... and get the mountpoint */
-	if (path_init(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
-		retval = path_walk(dir_name, &nd);
+	retval = path_lookup(dir_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
 	if (retval)
 		return retval;
 
@@ -826,7 +815,6 @@
 {
 	struct vfsmount *tmp;
 	struct nameidata new_nd, old_nd, parent_nd, root_parent, user_nd;
-	char *name;
 	int error;
 
 	if (!capable(CAP_SYS_ADMIN))
@@ -834,28 +822,14 @@
 
 	lock_kernel();
 
-	name = getname(new_root);
-	error = PTR_ERR(name);
-	if (IS_ERR(name))
-		goto out0;
-	error = 0;
-	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd))
-		error = path_walk(name, &new_nd);
-	putname(name);
+	error = __user_walk(new_root, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd);
 	if (error)
 		goto out0;
 	error = -EINVAL;
 	if (!check_mnt(new_nd.mnt))
 		goto out1;
 
-	name = getname(put_old);
-	error = PTR_ERR(name);
-	if (IS_ERR(name))
-		goto out1;
-	error = 0;
-	if (path_init(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd))
-		error = path_walk(name, &old_nd);
-	putname(name);
+	error = __user_walk(put_old, LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &old_nd);
 	if (error)
 		goto out1;
 
fs/open.c +2 -19
diff -Nru -X dontdiff linux-2.4.19-pre3-ac6/fs/open.c linux-path_lookup/fs/open.c
@@ -384,17 +384,8 @@
 {
 	int error;
 	struct nameidata nd;
-	char *name;
 
-	name = getname(filename);
-	error = PTR_ERR(name);
-	if (IS_ERR(name))
-		goto out;
-
-	error = 0;
-	if (path_init(name,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd))
-		error = path_walk(name, &nd);
-	putname(name);
+	error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
 	if (error)
 		goto out;
 
@@ -444,17 +435,9 @@
 {
 	int error;
 	struct nameidata nd;
-	char *name;
-
-	name = getname(filename);
-	error = PTR_ERR(name);
-	if (IS_ERR(name))
-		goto out;
 
-	path_init(name, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
+	error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
 		      LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
-	error = path_walk(name, &nd);	
-	putname(name);
 	if (error)
 		goto out;
 
fs/super.c +1 -2
diff -Nru -X dontdiff linux-2.4.19-pre3-ac6/fs/super.c linux-path_lookup/fs/super.c
@@ -575,8 +575,7 @@
 	/* What device it is? */
 	if (!dev_name || !*dev_name)
 		return ERR_PTR(-EINVAL);
-	if (path_init(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
-		error = path_walk(dev_name, &nd);
+	error = path_lookup(dev_name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd);
 	if (error)
 		return ERR_PTR(error);
 	inode = nd.dentry->d_inode;
include/linux/fs.h +1 -0
diff -Nru -X dontdiff linux-2.4.19-pre3-ac6/include/linux/fs.h linux-path_lookup/include/linux/fs.h
@@ -1348,6 +1348,7 @@
 extern int FASTCALL(__user_walk(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(path_init(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(path_walk(const char *, struct nameidata *));
+extern int FASTCALL(path_lookup(const char *, unsigned, struct nameidata *));
 extern int FASTCALL(link_path_walk(const char *, struct nameidata *));
 extern void path_release(struct nameidata *);
 extern int follow_down(struct vfsmount **, struct dentry **);