From: FUJITA Tomonori Date: Thu, 18 Dec 2008 05:49:36 +0000 (+0900) Subject: [SCSI] block: fix bio_add_page misuse with rq_map_data X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=e623ddb4e940b266adc77ba1cc28a3554aa90e79;p=linux-beck.git [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 Acked-by: Jens Axboe Signed-off-by: James Bottomley --- 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, ret = 0; i = 0; + if (map_data) + nr_pages = 1 << map_data->page_order; while (len) { - unsigned int bytes; - - if (map_data) - bytes = 1U << (PAGE_SHIFT + map_data->page_order); - else - bytes = PAGE_SIZE; + unsigned int bytes = PAGE_SIZE; if (bytes > len) bytes = len; if (map_data) { - if (i == map_data->nr_entries) { + if (i == map_data->nr_entries * nr_pages) { ret = -ENOMEM; break; } - page = map_data->pages[i++]; - } else + + page = map_data->pages[i / nr_pages]; + page += (i % nr_pages); + + i++; + } else { page = alloc_page(q->bounce_gfp | gfp_mask); - if (!page) { - ret = -ENOMEM; - break; + if (!page) { + ret = -ENOMEM; + break; + } } if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes)