summary refs log tree commit diff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 12:40:15 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-12 12:40:15 -0700
commit3272c544da48f8915a0e34189182aed029bd0f2b (patch)
treee2d6aacc2de8f26c14e844af6ed245b8a43d7978 /fs
parentff812d724254b95df76b7775d1359d856927a840 (diff)
downloadlinux-3272c544da48f8915a0e34189182aed029bd0f2b.tar.gz
vfs: use __getname/__putname for getcwd() system call
It's a pathname.  It should use the pathname allocators and
deallocators, and PATH_MAX instead of PAGE_SIZE.  Never mind that the
two are commonly the same.

With this, the allocations scale up nicely too, and I can do getcwd()
system calls at a rate of about 300M/s, with no lock contention
anywhere.

Of course, nobody sane does that, especially since getcwd() is
traditionally a very slow operation in Unix.  But this was also the
simplest way to benchmark the prepend_path() improvements by Waiman, and
once I saw the profiles I couldn't leave it well enough alone.

But apart from being an performance improvement (from using per-cpu slab
allocators instead of the raw page allocator), it's actually a valid and
real cleanup.

Signed-off-by: Linus "OCD" Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 29d58212aaf0..91e551b5af59 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3049,7 +3049,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 {
 	int error;
 	struct path pwd, root;
-	char *page = (char *) __get_free_page(GFP_USER);
+	char *page = __getname();
 
 	if (!page)
 		return -ENOMEM;
@@ -3061,8 +3061,8 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 	br_read_lock(&vfsmount_lock);
 	if (!d_unlinked(pwd.dentry)) {
 		unsigned long len;
-		char *cwd = page + PAGE_SIZE;
-		int buflen = PAGE_SIZE;
+		char *cwd = page + PATH_MAX;
+		int buflen = PATH_MAX;
 
 		prepend(&cwd, &buflen, "\0", 1);
 		error = prepend_path(&pwd, &root, &cwd, &buflen);
@@ -3080,7 +3080,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 		}
 
 		error = -ERANGE;
-		len = PAGE_SIZE + page - cwd;
+		len = PATH_MAX + page - cwd;
 		if (len <= size) {
 			error = len;
 			if (copy_to_user(buf, cwd, len))
@@ -3092,7 +3092,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
 	}
 
 out:
-	free_page((unsigned long) page);
+	__putname(page);
 	return error;
 }