diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-12-18 00:49:37 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-01-02 12:10:08 -0500 |
commit | 56c451f4b583ccdf80c9e676179c9cb49de86745 (patch) | |
tree | 7ad9daeafb88e3c4390bf7a2db0c203fe2642728 | |
parent | e623ddb4e940b266adc77ba1cc28a3554aa90e79 (diff) |
[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>
-rw-r--r-- | block/blk-map.c | 3 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 1 | ||||
-rw-r--r-- | fs/bio.c | 12 | ||||
-rw-r--r-- | include/linux/blkdev.h | 1 |
4 files changed, 14 insertions, 3 deletions
diff --git a/block/blk-map.c b/block/blk-map.c index 2990447f45e9..c7e55b23a2bc 100644 --- a/block/blk-map.c +++ b/block/blk-map.c | |||
@@ -150,6 +150,9 @@ int blk_rq_map_user(struct request_queue *q, struct request *rq, | |||
150 | bio = rq->bio; | 150 | bio = rq->bio; |
151 | bytes_read += ret; | 151 | bytes_read += ret; |
152 | ubuf += ret; | 152 | ubuf += ret; |
153 | |||
154 | if (map_data) | ||
155 | map_data->offset += ret; | ||
153 | } | 156 | } |
154 | 157 | ||
155 | if (!bio_flagged(bio, BIO_USER_MAPPED)) | 158 | if (!bio_flagged(bio, BIO_USER_MAPPED)) |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 5103855242ae..7d0b3d9ee43b 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1669,6 +1669,7 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
1669 | md->pages = req_schp->pages; | 1669 | md->pages = req_schp->pages; |
1670 | md->page_order = req_schp->page_order; | 1670 | md->page_order = req_schp->page_order; |
1671 | md->nr_entries = req_schp->k_use_sg; | 1671 | md->nr_entries = req_schp->k_use_sg; |
1672 | md->offset = 0; | ||
1672 | } | 1673 | } |
1673 | 1674 | ||
1674 | if (iov_count) | 1675 | if (iov_count) |
@@ -788,6 +788,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
788 | int i, ret; | 788 | int i, ret; |
789 | int nr_pages = 0; | 789 | int nr_pages = 0; |
790 | unsigned int len = 0; | 790 | unsigned int len = 0; |
791 | unsigned int offset = map_data ? map_data->offset & ~PAGE_MASK : 0; | ||
791 | 792 | ||
792 | for (i = 0; i < iov_count; i++) { | 793 | for (i = 0; i < iov_count; i++) { |
793 | unsigned long uaddr; | 794 | unsigned long uaddr; |
@@ -814,12 +815,16 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
814 | bio->bi_rw |= (!write_to_vm << BIO_RW); | 815 | bio->bi_rw |= (!write_to_vm << BIO_RW); |
815 | 816 | ||
816 | ret = 0; | 817 | ret = 0; |
817 | i = 0; | 818 | |
818 | if (map_data) | 819 | if (map_data) { |
819 | nr_pages = 1 << map_data->page_order; | 820 | nr_pages = 1 << map_data->page_order; |
821 | i = map_data->offset / PAGE_SIZE; | ||
822 | } | ||
820 | while (len) { | 823 | while (len) { |
821 | unsigned int bytes = PAGE_SIZE; | 824 | unsigned int bytes = PAGE_SIZE; |
822 | 825 | ||
826 | bytes -= offset; | ||
827 | |||
823 | if (bytes > len) | 828 | if (bytes > len) |
824 | bytes = len; | 829 | bytes = len; |
825 | 830 | ||
@@ -841,10 +846,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
841 | } | 846 | } |
842 | } | 847 | } |
843 | 848 | ||
844 | if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) | 849 | if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes) |
845 | break; | 850 | break; |
846 | 851 | ||
847 | len -= bytes; | 852 | len -= bytes; |
853 | offset = 0; | ||
848 | } | 854 | } |
849 | 855 | ||
850 | if (ret) | 856 | if (ret) |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7035cec583b6..811e5342c452 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -690,6 +690,7 @@ struct rq_map_data { | |||
690 | struct page **pages; | 690 | struct page **pages; |
691 | int page_order; | 691 | int page_order; |
692 | int nr_entries; | 692 | int nr_entries; |
693 | unsigned long offset; | ||
693 | }; | 694 | }; |
694 | 695 | ||
695 | struct req_iterator { | 696 | struct req_iterator { |