diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-12-18 08:49:37 +0300 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-01-02 20:10:08 +0300 |
commit | 56c451f4b583ccdf80c9e676179c9cb49de86745 (patch) | |
tree | 7ad9daeafb88e3c4390bf7a2db0c203fe2642728 /fs/bio.c | |
parent | e623ddb4e940b266adc77ba1cc28a3554aa90e79 (diff) | |
download | linux-56c451f4b583ccdf80c9e676179c9cb49de86745.tar.xz |
[SCSI] block: fix the partial mappings with struct rq_map_data
This fixes bio_copy_user_iov to properly handle the partial mappings
with struct rq_map_data (which only sg uses for now but st and osst
will shortly). It adds the offset member to struct rq_map_data and
changes blk_rq_map_user to update it so that bio_copy_user_iov can add
an appropriate page frame via bio_add_pc_page().
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 12 |
1 files changed, 9 insertions, 3 deletions
@@ -788,6 +788,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, int i, ret; int nr_pages = 0; unsigned int len = 0; + unsigned int offset = map_data ? map_data->offset & ~PAGE_MASK : 0; for (i = 0; i < iov_count; i++) { unsigned long uaddr; @@ -814,12 +815,16 @@ struct bio *bio_copy_user_iov(struct request_queue *q, bio->bi_rw |= (!write_to_vm << BIO_RW); ret = 0; - i = 0; - if (map_data) + + if (map_data) { nr_pages = 1 << map_data->page_order; + i = map_data->offset / PAGE_SIZE; + } while (len) { unsigned int bytes = PAGE_SIZE; + bytes -= offset; + if (bytes > len) bytes = len; @@ -841,10 +846,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q, } } - if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) + if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes) break; len -= bytes; + offset = 0; } if (ret) |