aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pipe.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2006-05-01 13:59:03 -0400
committerJens Axboe <axboe@suse.de>2006-05-01 13:59:03 -0400
commitf84d751994441292593523c7069ed147176f6cab (patch)
treea1a0c4836289df86bb62e7eae5c80c66fca1643a /fs/pipe.c
parent0568b409c74f7a125d92a09a3f386785700ef688 (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.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 888f265011bf..d9644fd9cc0d 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -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
113static void * anon_pipe_buf_map(struct file *file, struct pipe_inode_info *pipe, 113void *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
119static void anon_pipe_buf_unmap(struct pipe_inode_info *pipe, 119void 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
138static void anon_pipe_buf_get(struct pipe_inode_info *info, 138void 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
143int generic_pipe_buf_pin(struct pipe_inode_info *info, struct pipe_buffer *buf)
144{
145 return 0;
146}
147
144static struct pipe_buf_operations anon_pipe_buf_ops = { 148static 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
153static ssize_t 158static 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);