diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 21:40:15 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 21:40:15 +0200 |
commit | 3272c544da48f8915a0e34189182aed029bd0f2b (patch) | |
tree | e2d6aacc2de8f26c14e844af6ed245b8a43d7978 /fs | |
parent | vfs: don't copy things to user space holding the rcu readlock (diff) | |
download | linux-3272c544da48f8915a0e34189182aed029bd0f2b.tar.xz linux-3272c544da48f8915a0e34189182aed029bd0f2b.zip |
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.c | 10 |
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; } |