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 /fs/bio.c | |
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>
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, | |||
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) |