pos = file->f_pos;
        bvec_set_page(&bvec, page, PAGE_SIZE, 0);
        iov_iter_bvec(&iter, ITER_SOURCE, &bvec, 1, PAGE_SIZE);
+       iov_iter_set_copy_mc(&iter);
        n = __kernel_write_iter(cprm->file, &iter, &pos);
        if (n != PAGE_SIZE)
                return 0;
 
 
 struct iov_iter {
        u8 iter_type;
+       bool copy_mc;
        bool nofault;
        bool data_source;
        bool user_backed;
 
 #ifdef CONFIG_ARCH_HAS_COPY_MC
 size_t _copy_mc_to_iter(const void *addr, size_t bytes, struct iov_iter *i);
+static inline void iov_iter_set_copy_mc(struct iov_iter *i)
+{
+       i->copy_mc = true;
+}
+
+static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
+{
+       return i->copy_mc;
+}
 #else
 #define _copy_mc_to_iter _copy_to_iter
+static inline void iov_iter_set_copy_mc(struct iov_iter *i) { }
+static inline bool iov_iter_is_copy_mc(const struct iov_iter *i)
+{
+       return false;
+}
 #endif
 
 size_t iov_iter_zero(size_t bytes, struct iov_iter *);
        WARN_ON(direction & ~(READ | WRITE));
        *i = (struct iov_iter) {
                .iter_type = ITER_UBUF,
+               .copy_mc = false,
                .user_backed = true,
                .data_source = direction,
                .ubuf = buf,
 
        WARN_ON(direction & ~(READ | WRITE));
        *i = (struct iov_iter) {
                .iter_type = ITER_IOVEC,
+               .copy_mc = false,
                .nofault = false,
                .user_backed = true,
                .data_source = direction,
 EXPORT_SYMBOL_GPL(_copy_mc_to_iter);
 #endif /* CONFIG_ARCH_HAS_COPY_MC */
 
+static void *memcpy_from_iter(struct iov_iter *i, void *to, const void *from,
+                                size_t size)
+{
+       if (iov_iter_is_copy_mc(i))
+               return (void *)copy_mc_to_kernel(to, from, size);
+       return memcpy(to, from, size);
+}
+
 size_t _copy_from_iter(void *addr, size_t bytes, struct iov_iter *i)
 {
        if (WARN_ON_ONCE(!i->data_source))
                might_fault();
        iterate_and_advance(i, bytes, base, len, off,
                copyin(addr + off, base, len),
-               memcpy(addr + off, base, len)
+               memcpy_from_iter(i, addr + off, base, len)
        )
 
        return bytes;
        }
        iterate_and_advance(i, bytes, base, len, off,
                copyin(p + off, base, len),
-               memcpy(p + off, base, len)
+               memcpy_from_iter(i, p + off, base, len)
        )
        kunmap_atomic(kaddr);
        return bytes;
        WARN_ON(direction & ~(READ | WRITE));
        *i = (struct iov_iter){
                .iter_type = ITER_KVEC,
+               .copy_mc = false,
                .data_source = direction,
                .kvec = kvec,
                .nr_segs = nr_segs,
        WARN_ON(direction & ~(READ | WRITE));
        *i = (struct iov_iter){
                .iter_type = ITER_BVEC,
+               .copy_mc = false,
                .data_source = direction,
                .bvec = bvec,
                .nr_segs = nr_segs,
        BUG_ON(direction & ~1);
        *i = (struct iov_iter) {
                .iter_type = ITER_XARRAY,
+               .copy_mc = false,
                .data_source = direction,
                .xarray = xarray,
                .xarray_start = start,
        BUG_ON(direction != READ);
        *i = (struct iov_iter){
                .iter_type = ITER_DISCARD,
+               .copy_mc = false,
                .data_source = false,
                .count = count,
                .iov_offset = 0