diff options
author | Jens Axboe <axboe@suse.de> | 2006-05-01 13:59:03 -0400 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2006-05-01 13:59:03 -0400 |
commit | f84d751994441292593523c7069ed147176f6cab (patch) | |
tree | a1a0c4836289df86bb62e7eae5c80c66fca1643a /fs/pipe.c | |
parent | 0568b409c74f7a125d92a09a3f386785700ef688 (diff) |
[PATCH] pipe: introduce ->pin() buffer operation
The ->map() function is really expensive on highmem machines right now,
since it has to use the slower kmap() instead of kmap_atomic(). Splice
rarely needs to access the virtual address of a page, so it's a waste
of time doing it.
Introduce ->pin() to take over the responsibility of making sure the
page data is valid. ->map() is then reduced to just kmap(). That way we
can also share a most of the pipe buffer ops between pipe.c and splice.c
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 39 |
1 files changed, 23 insertions, 16 deletions
@@ -110,14 +110,14 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, | |||
110 | page_cache_release(page); | 110 | page_cache_release(page); |
111 | } | 111 | } |
112 | 112 | ||
113 | static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe, | 113 | void *generic_pipe_buf_map(struct pipe_inode_info *pipe, |
114 | struct pipe_buffer *buf) | 114 | struct pipe_buffer *buf) |
115 | { | 115 | { |
116 | return kmap(buf->page); | 116 | return kmap(buf->page); |
117 | } | 117 | } |
118 | 118 | ||
119 | static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe, | 119 | void generic_pipe_buf_unmap(struct pipe_inode_info *pipe, |
120 | struct pipe_buffer *buf) | 120 | struct pipe_buffer *buf) |
121 | { | 121 | { |
122 | kunmap(buf->page); | 122 | kunmap(buf->page); |
123 | } | 123 | } |
@@ -135,19 +135,24 @@ static int anon_pipe_buf_steal(struct pipe_inode_info *pipe, | |||
135 | return 1; | 135 | return 1; |
136 | } | 136 | } |
137 | 137 | ||
138 | static void anon_pipe_buf_get(struct pipe_inode_info *info, | 138 | void generic_pipe_buf_get(struct pipe_inode_info *info, struct pipe_buffer *buf) |
139 | struct pipe_buffer *buf) | ||
140 | { | 139 | { |
141 | page_cache_get(buf->page); | 140 | page_cache_get(buf->page); |
142 | } | 141 | } |
143 | 142 | ||
143 | int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf) | ||
144 | { | ||
145 | return 0; | ||
146 | } | ||
147 | |||
144 | static struct pipe_buf_operations anon_pipe_buf_ops = { | 148 | static struct pipe_buf_operations anon_pipe_buf_ops = { |
145 | .can_merge = 1, | 149 | .can_merge = 1, |
146 | .map = anon_pipe_buf_map, | 150 | .map = generic_pipe_buf_map, |
147 | .unmap = anon_pipe_buf_unmap, | 151 | .unmap = generic_pipe_buf_unmap, |
152 | .pin = generic_pipe_buf_pin, | ||
148 | .release = anon_pipe_buf_release, | 153 | .release = anon_pipe_buf_release, |
149 | .steal = anon_pipe_buf_steal, | 154 | .steal = anon_pipe_buf_steal, |
150 | .get = anon_pipe_buf_get, | 155 | .get = generic_pipe_buf_get, |
151 | }; | 156 | }; |
152 | 157 | ||
153 | static ssize_t | 158 | static ssize_t |
@@ -183,12 +188,14 @@ pipe_readv(struct file *filp, const struct iovec *_iov, | |||
183 | if (chars > total_len) | 188 | if (chars > total_len) |
184 | chars = total_len; | 189 | chars = total_len; |
185 | 190 | ||
186 | addr = ops->map(filp, pipe, buf); | 191 | error = ops->pin(pipe, buf); |
187 | if (IS_ERR(addr)) { | 192 | if (error) { |
188 | if (!ret) | 193 | if (!ret) |
189 | ret = PTR_ERR(addr); | 194 | error = ret; |
190 | break; | 195 | break; |
191 | } | 196 | } |
197 | |||
198 | addr = ops->map(pipe, buf); | ||
192 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); | 199 | error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars); |
193 | ops->unmap(pipe, buf); | 200 | ops->unmap(pipe, buf); |
194 | if (unlikely(error)) { | 201 | if (unlikely(error)) { |
@@ -300,11 +307,11 @@ pipe_writev(struct file *filp, const struct iovec *_iov, | |||
300 | void *addr; | 307 | void *addr; |
301 | int error; | 308 | int error; |
302 | 309 | ||
303 | addr = ops->map(filp, pipe, buf); | 310 | error = ops->pin(pipe, buf); |
304 | if (IS_ERR(addr)) { | 311 | if (error) |
305 | error = PTR_ERR(addr); | ||
306 | goto out; | 312 | goto out; |
307 | } | 313 | |
314 | addr = ops->map(pipe, buf); | ||
308 | error = pipe_iov_copy_from_user(offset + addr, iov, | 315 | error = pipe_iov_copy_from_user(offset + addr, iov, |
309 | chars); | 316 | chars); |
310 | ops->unmap(pipe, buf); | 317 | ops->unmap(pipe, buf); |