Merge tag 'thermal-v5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/therma...
[linux-2.6-microblaze.git] / lib / iov_iter.c
index ba7eb65..e23123a 100644 (file)
@@ -465,7 +465,6 @@ void iov_iter_init(struct iov_iter *i, unsigned int direction,
                        size_t count)
 {
        WARN_ON(direction & ~(READ | WRITE));
-       WARN_ON_ONCE(uaccess_kernel());
        *i = (struct iov_iter) {
                .iter_type = ITER_IOVEC,
                .data_source = direction,
@@ -582,39 +581,34 @@ static __wsum csum_and_memcpy(void *to, const void *from, size_t len,
 }
 
 static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
-                                        struct csum_state *csstate,
-                                        struct iov_iter *i)
+                                        struct iov_iter *i, __wsum *sump)
 {
        struct pipe_inode_info *pipe = i->pipe;
        unsigned int p_mask = pipe->ring_size - 1;
-       __wsum sum = csstate->csum;
-       size_t off = csstate->off;
+       __wsum sum = *sump;
+       size_t off = 0;
        unsigned int i_head;
-       size_t n, r;
+       size_t r;
 
        if (!sanity(i))
                return 0;
 
-       bytes = n = push_pipe(i, bytes, &i_head, &r);
-       if (unlikely(!n))
-               return 0;
-       do {
-               size_t chunk = min_t(size_t, n, PAGE_SIZE - r);
-               char *p = kmap_atomic(pipe->bufs[i_head & p_mask].page);
-               sum = csum_and_memcpy(p + r, addr, chunk, sum, off);
-               kunmap_atomic(p);
+       bytes = push_pipe(i, bytes, &i_head, &r);
+       while (bytes) {
+               size_t chunk = min_t(size_t, bytes, PAGE_SIZE - r);
+               char *p = kmap_local_page(pipe->bufs[i_head & p_mask].page);
+               sum = csum_and_memcpy(p + r, addr + off, chunk, sum, off);
+               kunmap_local(p);
                i->head = i_head;
                i->iov_offset = r + chunk;
-               n -= chunk;
+               bytes -= chunk;
                off += chunk;
-               addr += chunk;
                r = 0;
                i_head++;
-       } while (n);
-       i->count -= bytes;
-       csstate->csum = sum;
-       csstate->off = off;
-       return bytes;
+       }
+       *sump = sum;
+       i->count -= off;
+       return off;
 }
 
 size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
@@ -642,19 +636,6 @@ static int copyout_mc(void __user *to, const void *from, size_t n)
        return n;
 }
 
-static unsigned long copy_mc_to_page(struct page *page, size_t offset,
-               const char *from, size_t len)
-{
-       unsigned long ret;
-       char *to;
-
-       to = kmap_atomic(page);
-       ret = copy_mc_to_kernel(to + offset, from, len);
-       kunmap_atomic(to);
-
-       return ret;
-}
-
 static size_t copy_mc_pipe_to_iter(const void *addr, size_t bytes,
                                struct iov_iter *i)
 {
@@ -666,25 +647,23 @@ static size_t copy_mc_pipe_to_iter(const void *addr, size_t bytes,
        if (!sanity(i))
                return 0;
 
-       bytes = n = push_pipe(i, bytes, &i_head, &off);
-       if (unlikely(!n))
-               return 0;
-       do {
+       n = push_pipe(i, bytes, &i_head, &off);
+       while (n) {
                size_t chunk = min_t(size_t, n, PAGE_SIZE - off);
+               char *p = kmap_local_page(pipe->bufs[i_head & p_mask].page);
                unsigned long rem;
-
-               rem = copy_mc_to_page(pipe->bufs[i_head & p_mask].page,
-                                           off, addr, chunk);
+               rem = copy_mc_to_kernel(p + off, addr + xfer, chunk);
+               chunk -= rem;
+               kunmap_local(p);
                i->head = i_head;
-               i->iov_offset = off + chunk - rem;
-               xfer += chunk - rem;
+               i->iov_offset = off + chunk;
+               xfer += chunk;
                if (rem)
                        break;
                n -= chunk;
-               addr += chunk;
                off = 0;
                i_head++;
-       } while (n);
+       }
        i->count -= xfer;
        return xfer;
 }
@@ -897,7 +876,9 @@ static size_t pipe_zero(size_t bytes, struct iov_iter *i)
 
        do {
                size_t chunk = min_t(size_t, n, PAGE_SIZE - off);
-               memzero_page(pipe->bufs[i_head & p_mask].page, off, chunk);
+               char *p = kmap_local_page(pipe->bufs[i_head & p_mask].page);
+               memset(p + off, 0, chunk);
+               kunmap_local(p);
                i->head = i_head;
                i->iov_offset = off + chunk;
                n -= chunk;
@@ -1665,8 +1646,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum,
        }
        iterate_and_advance(i, bytes, base, len, off, ({
                next = csum_and_copy_from_user(base, addr + off, len);
-               if (next)
-                       sum = csum_block_add(sum, next, off);
+               sum = csum_block_add(sum, next, off);
                next ? 0 : len;
        }), ({
                sum = csum_and_memcpy(addr + off, base, len, sum, off);
@@ -1683,18 +1663,17 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, void *_csstate,
        struct csum_state *csstate = _csstate;
        __wsum sum, next;
 
-       if (unlikely(iov_iter_is_pipe(i)))
-               return csum_and_copy_to_pipe_iter(addr, bytes, _csstate, i);
-
-       sum = csum_shift(csstate->csum, csstate->off);
        if (unlikely(iov_iter_is_discard(i))) {
                WARN_ON(1);     /* for now */
                return 0;
        }
-       iterate_and_advance(i, bytes, base, len, off, ({
+
+       sum = csum_shift(csstate->csum, csstate->off);
+       if (unlikely(iov_iter_is_pipe(i)))
+               bytes = csum_and_copy_to_pipe_iter(addr, bytes, i, &sum);
+       else iterate_and_advance(i, bytes, base, len, off, ({
                next = csum_and_copy_to_user(addr + off, base, len);
-               if (next)
-                       sum = csum_block_add(sum, next, off);
+               sum = csum_block_add(sum, next, off);
                next ? 0 : len;
        }), ({
                sum = csum_and_memcpy(base, addr + off, len, sum, off);