diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/pktcdvd.c | 43 |
1 files changed, 17 insertions, 26 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 89d8fe014efa..93e44d0292ab 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -645,7 +645,7 @@ static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct pag | |||
645 | * b) The data can be used as cache to avoid read requests if we receive a | 645 | * b) The data can be used as cache to avoid read requests if we receive a |
646 | * new write request for the same zone. | 646 | * new write request for the same zone. |
647 | */ | 647 | */ |
648 | static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, int *offsets) | 648 | static void pkt_make_local_copy(struct packet_data *pkt, struct bio_vec *bvec) |
649 | { | 649 | { |
650 | int f, p, offs; | 650 | int f, p, offs; |
651 | 651 | ||
@@ -653,15 +653,15 @@ static void pkt_make_local_copy(struct packet_data *pkt, struct page **pages, in | |||
653 | p = 0; | 653 | p = 0; |
654 | offs = 0; | 654 | offs = 0; |
655 | for (f = 0; f < pkt->frames; f++) { | 655 | for (f = 0; f < pkt->frames; f++) { |
656 | if (pages[f] != pkt->pages[p]) { | 656 | if (bvec[f].bv_page != pkt->pages[p]) { |
657 | void *vfrom = kmap_atomic(pages[f], KM_USER0) + offsets[f]; | 657 | void *vfrom = kmap_atomic(bvec[f].bv_page, KM_USER0) + bvec[f].bv_offset; |
658 | void *vto = page_address(pkt->pages[p]) + offs; | 658 | void *vto = page_address(pkt->pages[p]) + offs; |
659 | memcpy(vto, vfrom, CD_FRAMESIZE); | 659 | memcpy(vto, vfrom, CD_FRAMESIZE); |
660 | kunmap_atomic(vfrom, KM_USER0); | 660 | kunmap_atomic(vfrom, KM_USER0); |
661 | pages[f] = pkt->pages[p]; | 661 | bvec[f].bv_page = pkt->pages[p]; |
662 | offsets[f] = offs; | 662 | bvec[f].bv_offset = offs; |
663 | } else { | 663 | } else { |
664 | BUG_ON(offsets[f] != offs); | 664 | BUG_ON(bvec[f].bv_offset != offs); |
665 | } | 665 | } |
666 | offs += CD_FRAMESIZE; | 666 | offs += CD_FRAMESIZE; |
667 | if (offs >= PAGE_SIZE) { | 667 | if (offs >= PAGE_SIZE) { |
@@ -991,18 +991,17 @@ try_next_bio: | |||
991 | static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | 991 | static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) |
992 | { | 992 | { |
993 | struct bio *bio; | 993 | struct bio *bio; |
994 | struct page *pages[PACKET_MAX_SIZE]; | ||
995 | int offsets[PACKET_MAX_SIZE]; | ||
996 | int f; | 994 | int f; |
997 | int frames_write; | 995 | int frames_write; |
996 | struct bio_vec *bvec = pkt->w_bio->bi_io_vec; | ||
998 | 997 | ||
999 | for (f = 0; f < pkt->frames; f++) { | 998 | for (f = 0; f < pkt->frames; f++) { |
1000 | pages[f] = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; | 999 | bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE]; |
1001 | offsets[f] = (f * CD_FRAMESIZE) % PAGE_SIZE; | 1000 | bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE; |
1002 | } | 1001 | } |
1003 | 1002 | ||
1004 | /* | 1003 | /* |
1005 | * Fill-in pages[] and offsets[] with data from orig_bios. | 1004 | * Fill-in bvec with data from orig_bios. |
1006 | */ | 1005 | */ |
1007 | frames_write = 0; | 1006 | frames_write = 0; |
1008 | spin_lock(&pkt->lock); | 1007 | spin_lock(&pkt->lock); |
@@ -1024,11 +1023,11 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1024 | } | 1023 | } |
1025 | 1024 | ||
1026 | if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) { | 1025 | if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) { |
1027 | pages[f] = src_bvl->bv_page; | 1026 | bvec[f].bv_page = src_bvl->bv_page; |
1028 | offsets[f] = src_bvl->bv_offset + src_offs; | 1027 | bvec[f].bv_offset = src_bvl->bv_offset + src_offs; |
1029 | } else { | 1028 | } else { |
1030 | pkt_copy_bio_data(bio, segment, src_offs, | 1029 | pkt_copy_bio_data(bio, segment, src_offs, |
1031 | pages[f], offsets[f]); | 1030 | bvec[f].bv_page, bvec[f].bv_offset); |
1032 | } | 1031 | } |
1033 | src_offs += CD_FRAMESIZE; | 1032 | src_offs += CD_FRAMESIZE; |
1034 | frames_write++; | 1033 | frames_write++; |
@@ -1042,7 +1041,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1042 | BUG_ON(frames_write != pkt->write_size); | 1041 | BUG_ON(frames_write != pkt->write_size); |
1043 | 1042 | ||
1044 | if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) { | 1043 | if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) { |
1045 | pkt_make_local_copy(pkt, pages, offsets); | 1044 | pkt_make_local_copy(pkt, bvec); |
1046 | pkt->cache_valid = 1; | 1045 | pkt->cache_valid = 1; |
1047 | } else { | 1046 | } else { |
1048 | pkt->cache_valid = 0; | 1047 | pkt->cache_valid = 0; |
@@ -1055,17 +1054,9 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) | |||
1055 | pkt->w_bio->bi_bdev = pd->bdev; | 1054 | pkt->w_bio->bi_bdev = pd->bdev; |
1056 | pkt->w_bio->bi_end_io = pkt_end_io_packet_write; | 1055 | pkt->w_bio->bi_end_io = pkt_end_io_packet_write; |
1057 | pkt->w_bio->bi_private = pkt; | 1056 | pkt->w_bio->bi_private = pkt; |
1058 | for (f = 0; f < pkt->frames; f++) { | 1057 | for (f = 0; f < pkt->frames; f++) |
1059 | if ((f + 1 < pkt->frames) && (pages[f + 1] == pages[f]) && | 1058 | if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset)) |
1060 | (offsets[f + 1] = offsets[f] + CD_FRAMESIZE)) { | 1059 | BUG(); |
1061 | if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE * 2, offsets[f])) | ||
1062 | BUG(); | ||
1063 | f++; | ||
1064 | } else { | ||
1065 | if (!bio_add_page(pkt->w_bio, pages[f], CD_FRAMESIZE, offsets[f])) | ||
1066 | BUG(); | ||
1067 | } | ||
1068 | } | ||
1069 | VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt); | 1060 | VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt); |
1070 | 1061 | ||
1071 | atomic_set(&pkt->io_wait, 1); | 1062 | atomic_set(&pkt->io_wait, 1); |