diff options
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); |
