aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-12-18 00:49:37 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-01-02 12:10:08 -0500
commit56c451f4b583ccdf80c9e676179c9cb49de86745 (patch)
tree7ad9daeafb88e3c4390bf7a2db0c203fe2642728
parente623ddb4e940b266adc77ba1cc28a3554aa90e79 (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.c3
-rw-r--r--drivers/scsi/sg.c1
-rw-r--r--fs/bio.c12
-rw-r--r--include/linux/blkdev.h1
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)
diff --git a/fs/bio.c b/fs/bio.c
index 356e7423b923..13be075806b6 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -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
695struct req_iterator { 696struct req_iterator {