diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 15:40:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-12 15:40:15 -0400 |
commit | 3272c544da48f8915a0e34189182aed029bd0f2b (patch) | |
tree | e2d6aacc2de8f26c14e844af6ed245b8a43d7978 /fs/dcache.c | |
parent | ff812d724254b95df76b7775d1359d856927a840 (diff) |
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/dcache.c')
-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) | |||
3049 | { | 3049 | { |
3050 | int error; | 3050 | int error; |
3051 | struct path pwd, root; | 3051 | struct path pwd, root; |
3052 | char *page = (char *) __get_free_page(GFP_USER); | 3052 | char *page = __getname(); |
3053 | 3053 | ||
3054 | if (!page) | 3054 | if (!page) |
3055 | return -ENOMEM; | 3055 | return -ENOMEM; |
@@ -3061,8 +3061,8 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) | |||
3061 | br_read_lock(&vfsmount_lock); | 3061 | br_read_lock(&vfsmount_lock); |
3062 | if (!d_unlinked(pwd.dentry)) { | 3062 | if (!d_unlinked(pwd.dentry)) { |
3063 | unsigned long len; | 3063 | unsigned long len; |
3064 | char *cwd = page + PAGE_SIZE; | 3064 | char *cwd = page + PATH_MAX; |
3065 | int buflen = PAGE_SIZE; | 3065 | int buflen = PATH_MAX; |
3066 | 3066 | ||
3067 | prepend(&cwd, &buflen, "\0", 1); | 3067 | prepend(&cwd, &buflen, "\0", 1); |
3068 | error = prepend_path(&pwd, &root, &cwd, &buflen); | 3068 | error = prepend_path(&pwd, &root, &cwd, &buflen); |
@@ -3080,7 +3080,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) | |||
3080 | } | 3080 | } |
3081 | 3081 | ||
3082 | error = -ERANGE; | 3082 | error = -ERANGE; |
3083 | len = PAGE_SIZE + page - cwd; | 3083 | len = PATH_MAX + page - cwd; |
3084 | if (len <= size) { | 3084 | if (len <= size) { |
3085 | error = len; | 3085 | error = len; |
3086 | if (copy_to_user(buf, cwd, len)) | 3086 | if (copy_to_user(buf, cwd, len)) |
@@ -3092,7 +3092,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) | |||
3092 | } | 3092 | } |
3093 | 3093 | ||
3094 | out: | 3094 | out: |
3095 | free_page((unsigned long) page); | 3095 | __putname(page); |
3096 | return error; | 3096 | return error; |
3097 | } | 3097 | } |
3098 | 3098 | ||