Loading fs/pipe.c +8 −71 Original line number Diff line number Diff line Loading @@ -142,55 +142,6 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, return 0; } static int pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, int atomic) { unsigned long copy; while (len > 0) { while (!iov->iov_len) iov++; copy = min_t(unsigned long, len, iov->iov_len); if (atomic) { if (__copy_to_user_inatomic(iov->iov_base, from, copy)) return -EFAULT; } else { if (copy_to_user(iov->iov_base, from, copy)) return -EFAULT; } from += copy; len -= copy; iov->iov_base += copy; iov->iov_len -= copy; } return 0; } /* * Attempt to pre-fault in the user memory, so we can use atomic copies. * Returns the number of bytes not faulted in. */ static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len) { while (!iov->iov_len) iov++; while (len > 0) { unsigned long this_len; this_len = min_t(unsigned long, len, iov->iov_len); if (fault_in_pages_writeable(iov->iov_base, this_len)) break; len -= this_len; iov++; } return len; } /* * Pre-fault in the user memory, so we can use atomic copies. */ Loading Loading @@ -329,12 +280,15 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, ssize_t ret; struct iovec *iov = (struct iovec *)_iov; size_t total_len; struct iov_iter iter; total_len = iov_length(iov, nr_segs); /* Null read succeeds. */ if (unlikely(total_len == 0)) return 0; iov_iter_init(&iter, iov, nr_segs, total_len, 0); do_wakeup = 0; ret = 0; __pipe_lock(pipe); Loading @@ -344,9 +298,9 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, int curbuf = pipe->curbuf; struct pipe_buffer *buf = pipe->bufs + curbuf; const struct pipe_buf_operations *ops = buf->ops; void *addr; size_t chars = buf->len; int error, atomic; size_t written; int error; if (chars > total_len) chars = total_len; Loading @@ -358,27 +312,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, break; } atomic = !iov_fault_in_pages_write(iov, chars); redo: if (atomic) addr = kmap_atomic(buf->page); else addr = kmap(buf->page); error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); if (atomic) kunmap_atomic(addr); else kunmap(buf->page); if (unlikely(error)) { /* * Just retry with the slow path if we failed. */ if (atomic) { atomic = 0; goto redo; } written = copy_page_to_iter(buf->page, buf->offset, chars, &iter); if (unlikely(written < chars)) { if (!ret) ret = error; ret = -EFAULT; break; } ret += chars; Loading Loading
fs/pipe.c +8 −71 Original line number Diff line number Diff line Loading @@ -142,55 +142,6 @@ pipe_iov_copy_from_user(void *to, struct iovec *iov, unsigned long len, return 0; } static int pipe_iov_copy_to_user(struct iovec *iov, const void *from, unsigned long len, int atomic) { unsigned long copy; while (len > 0) { while (!iov->iov_len) iov++; copy = min_t(unsigned long, len, iov->iov_len); if (atomic) { if (__copy_to_user_inatomic(iov->iov_base, from, copy)) return -EFAULT; } else { if (copy_to_user(iov->iov_base, from, copy)) return -EFAULT; } from += copy; len -= copy; iov->iov_base += copy; iov->iov_len -= copy; } return 0; } /* * Attempt to pre-fault in the user memory, so we can use atomic copies. * Returns the number of bytes not faulted in. */ static int iov_fault_in_pages_write(struct iovec *iov, unsigned long len) { while (!iov->iov_len) iov++; while (len > 0) { unsigned long this_len; this_len = min_t(unsigned long, len, iov->iov_len); if (fault_in_pages_writeable(iov->iov_base, this_len)) break; len -= this_len; iov++; } return len; } /* * Pre-fault in the user memory, so we can use atomic copies. */ Loading Loading @@ -329,12 +280,15 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, ssize_t ret; struct iovec *iov = (struct iovec *)_iov; size_t total_len; struct iov_iter iter; total_len = iov_length(iov, nr_segs); /* Null read succeeds. */ if (unlikely(total_len == 0)) return 0; iov_iter_init(&iter, iov, nr_segs, total_len, 0); do_wakeup = 0; ret = 0; __pipe_lock(pipe); Loading @@ -344,9 +298,9 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, int curbuf = pipe->curbuf; struct pipe_buffer *buf = pipe->bufs + curbuf; const struct pipe_buf_operations *ops = buf->ops; void *addr; size_t chars = buf->len; int error, atomic; size_t written; int error; if (chars > total_len) chars = total_len; Loading @@ -358,27 +312,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, break; } atomic = !iov_fault_in_pages_write(iov, chars); redo: if (atomic) addr = kmap_atomic(buf->page); else addr = kmap(buf->page); error = pipe_iov_copy_to_user(iov, addr + buf->offset, chars, atomic); if (atomic) kunmap_atomic(addr); else kunmap(buf->page); if (unlikely(error)) { /* * Just retry with the slow path if we failed. */ if (atomic) { atomic = 0; goto redo; } written = copy_page_to_iter(buf->page, buf->offset, chars, &iter); if (unlikely(written < chars)) { if (!ret) ret = error; ret = -EFAULT; break; } ret += chars; Loading