Loading block/bio.c +24 −33 Original line number Diff line number Diff line Loading @@ -1328,7 +1328,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct page **pages; struct bio *bio; int cur_page = 0; int ret, offset; int ret; struct iov_iter i; struct iovec iov; struct bio_vec *bvec; Loading Loading @@ -1365,43 +1365,32 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (!pages) goto out; iov_for_each(iov, i, *iter) { unsigned long uaddr = (unsigned long) iov.iov_base; unsigned long len = iov.iov_len; unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; const int local_nr_pages = end - start; const int page_limit = cur_page + local_nr_pages; ret = get_user_pages_fast(uaddr, local_nr_pages, (iter->type & WRITE) != WRITE, &pages[cur_page]); if (unlikely(ret < local_nr_pages)) { for (j = cur_page; j < page_limit; j++) { if (!pages[j]) break; put_page(pages[j]); } ret = -EFAULT; i = *iter; while (iov_iter_count(&i)) { ssize_t bytes; size_t offs, added = 0; int npages; bytes = iov_iter_get_pages(&i, pages + cur_page, LONG_MAX, nr_pages - cur_page, &offs); if (unlikely(bytes <= 0)) { ret = bytes ? bytes : -EFAULT; goto out_unmap; } offset = offset_in_page(uaddr); for (j = cur_page; j < page_limit; j++) { unsigned int bytes = PAGE_SIZE - offset; unsigned short prev_bi_vcnt = bio->bi_vcnt; npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE); if (len <= 0) break; for (j = cur_page; j < cur_page + npages; j++) { unsigned int n = PAGE_SIZE - offs; unsigned short prev_bi_vcnt = bio->bi_vcnt; if (bytes > len) bytes = len; if (n > bytes) n = bytes; /* * sorry... */ if (bio_add_pc_page(q, bio, pages[j], bytes, offset) < bytes) if (bio_add_pc_page(q, bio, pages[j], n, offs) < n) break; /* Loading @@ -1411,16 +1400,18 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (bio->bi_vcnt == prev_bi_vcnt) put_page(pages[j]); len -= bytes; offset = 0; added += n; bytes -= n; offs = 0; } iov_iter_advance(&i, added); cur_page = j; /* * release the pages we didn't map into the bio, if any */ while (j < page_limit) while (j < cur_page + npages) put_page(pages[j++]); cur_page = j; } kfree(pages); Loading Loading
block/bio.c +24 −33 Original line number Diff line number Diff line Loading @@ -1328,7 +1328,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, struct page **pages; struct bio *bio; int cur_page = 0; int ret, offset; int ret; struct iov_iter i; struct iovec iov; struct bio_vec *bvec; Loading Loading @@ -1365,43 +1365,32 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (!pages) goto out; iov_for_each(iov, i, *iter) { unsigned long uaddr = (unsigned long) iov.iov_base; unsigned long len = iov.iov_len; unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; unsigned long start = uaddr >> PAGE_SHIFT; const int local_nr_pages = end - start; const int page_limit = cur_page + local_nr_pages; ret = get_user_pages_fast(uaddr, local_nr_pages, (iter->type & WRITE) != WRITE, &pages[cur_page]); if (unlikely(ret < local_nr_pages)) { for (j = cur_page; j < page_limit; j++) { if (!pages[j]) break; put_page(pages[j]); } ret = -EFAULT; i = *iter; while (iov_iter_count(&i)) { ssize_t bytes; size_t offs, added = 0; int npages; bytes = iov_iter_get_pages(&i, pages + cur_page, LONG_MAX, nr_pages - cur_page, &offs); if (unlikely(bytes <= 0)) { ret = bytes ? bytes : -EFAULT; goto out_unmap; } offset = offset_in_page(uaddr); for (j = cur_page; j < page_limit; j++) { unsigned int bytes = PAGE_SIZE - offset; unsigned short prev_bi_vcnt = bio->bi_vcnt; npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE); if (len <= 0) break; for (j = cur_page; j < cur_page + npages; j++) { unsigned int n = PAGE_SIZE - offs; unsigned short prev_bi_vcnt = bio->bi_vcnt; if (bytes > len) bytes = len; if (n > bytes) n = bytes; /* * sorry... */ if (bio_add_pc_page(q, bio, pages[j], bytes, offset) < bytes) if (bio_add_pc_page(q, bio, pages[j], n, offs) < n) break; /* Loading @@ -1411,16 +1400,18 @@ struct bio *bio_map_user_iov(struct request_queue *q, if (bio->bi_vcnt == prev_bi_vcnt) put_page(pages[j]); len -= bytes; offset = 0; added += n; bytes -= n; offs = 0; } iov_iter_advance(&i, added); cur_page = j; /* * release the pages we didn't map into the bio, if any */ while (j < page_limit) while (j < cur_page + npages) put_page(pages[j++]); cur_page = j; } kfree(pages); Loading