aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-12-18 00:49:36 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-01-02 12:09:41 -0500
commite623ddb4e940b266adc77ba1cc28a3554aa90e79 (patch)
tree62c245b32720573d97718795b0c8165cad967b05
parent4f10aae0d1a285df6b16bf6ca5abd366140fd371 (diff)
[SCSI] block: fix bio_add_page misuse with rq_map_data
This fixes bio_add_page misuse in bio_copy_user_iov with rq_map_data, which only sg uses now. rq_map_data carries page frames for bio_add_pc_page. bio_copy_user_iov uses bio_add_pc_page with a larger size than PAGE_SIZE. It's clearly wrong. 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--fs/bio.c26
1 files changed, 14 insertions, 12 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 711cee103602..356e7423b923 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -815,28 +815,30 @@ struct bio *bio_copy_user_iov(struct request_queue *q,
815 815
816 ret = 0; 816 ret = 0;
817 i = 0; 817 i = 0;
818 if (map_data)
819 nr_pages = 1 << map_data->page_order;
818 while (len) { 820 while (len) {
819 unsigned int bytes; 821 unsigned int bytes = PAGE_SIZE;
820
821 if (map_data)
822 bytes = 1U << (PAGE_SHIFT + map_data->page_order);
823 else
824 bytes = PAGE_SIZE;
825 822
826 if (bytes > len) 823 if (bytes > len)
827 bytes = len; 824 bytes = len;
828 825
829 if (map_data) { 826 if (map_data) {
830 if (i == map_data->nr_entries) { 827 if (i == map_data->nr_entries * nr_pages) {
831 ret = -ENOMEM; 828 ret = -ENOMEM;
832 break; 829 break;
833 } 830 }
834 page = map_data->pages[i++]; 831
835 } else 832 page = map_data->pages[i / nr_pages];
833 page += (i % nr_pages);
834
835 i++;
836 } else {
836 page = alloc_page(q->bounce_gfp | gfp_mask); 837 page = alloc_page(q->bounce_gfp | gfp_mask);
837 if (!page) { 838 if (!page) {
838 ret = -ENOMEM; 839 ret = -ENOMEM;
839 break; 840 break;
841 }
840 } 842 }
841 843
842 if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) 844 if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)