提交 076098e5 编写于 作者: A Al Viro

bio_map_user_iov(): switch to iov_iter_get_pages()/iov_iter_advance()

... and to hell with iov_for_each() nonsense
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 1cfd0ddd
...@@ -1328,7 +1328,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, ...@@ -1328,7 +1328,7 @@ struct bio *bio_map_user_iov(struct request_queue *q,
struct page **pages; struct page **pages;
struct bio *bio; struct bio *bio;
int cur_page = 0; int cur_page = 0;
int ret, offset; int ret;
struct iov_iter i; struct iov_iter i;
struct iovec iov; struct iovec iov;
struct bio_vec *bvec; struct bio_vec *bvec;
...@@ -1365,43 +1365,32 @@ struct bio *bio_map_user_iov(struct request_queue *q, ...@@ -1365,43 +1365,32 @@ struct bio *bio_map_user_iov(struct request_queue *q,
if (!pages) if (!pages)
goto out; goto out;
iov_for_each(iov, i, *iter) { i = *iter;
unsigned long uaddr = (unsigned long) iov.iov_base; while (iov_iter_count(&i)) {
unsigned long len = iov.iov_len; ssize_t bytes;
unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; size_t offs, added = 0;
unsigned long start = uaddr >> PAGE_SHIFT; int npages;
const int local_nr_pages = end - start;
const int page_limit = cur_page + local_nr_pages; bytes = iov_iter_get_pages(&i, pages + cur_page, LONG_MAX,
nr_pages - cur_page, &offs);
ret = get_user_pages_fast(uaddr, local_nr_pages, if (unlikely(bytes <= 0)) {
(iter->type & WRITE) != WRITE, ret = bytes ? bytes : -EFAULT;
&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;
goto out_unmap; goto out_unmap;
} }
offset = offset_in_page(uaddr); npages = DIV_ROUND_UP(offs + bytes, PAGE_SIZE);
for (j = cur_page; j < page_limit; j++) {
unsigned int bytes = PAGE_SIZE - offset; for (j = cur_page; j < cur_page + npages; j++) {
unsigned int n = PAGE_SIZE - offs;
unsigned short prev_bi_vcnt = bio->bi_vcnt; unsigned short prev_bi_vcnt = bio->bi_vcnt;
if (len <= 0) if (n > bytes)
break; n = bytes;
if (bytes > len)
bytes = len;
/* /*
* sorry... * sorry...
*/ */
if (bio_add_pc_page(q, bio, pages[j], bytes, offset) < if (bio_add_pc_page(q, bio, pages[j], n, offs) < n)
bytes)
break; break;
/* /*
...@@ -1411,16 +1400,18 @@ struct bio *bio_map_user_iov(struct request_queue *q, ...@@ -1411,16 +1400,18 @@ struct bio *bio_map_user_iov(struct request_queue *q,
if (bio->bi_vcnt == prev_bi_vcnt) if (bio->bi_vcnt == prev_bi_vcnt)
put_page(pages[j]); put_page(pages[j]);
len -= bytes; added += n;
offset = 0; bytes -= n;
offs = 0;
} }
iov_iter_advance(&i, added);
cur_page = j;
/* /*
* release the pages we didn't map into the bio, if any * 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++]); put_page(pages[j++]);
cur_page = j;
} }
kfree(pages); kfree(pages);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册