From: Jens Axboe idefloppy_input_buffers looks buggy wrt bio traversal, I bet that is the problem. This is a first stab at bringing it into line. Also kills pc->b_data, noone should do stuff like that. And IDEFLOPPY_MIN and _MAX. drivers/ide/ide-floppy.c | 95 ++++++++++++++++++++++------------------------- 1 files changed, 46 insertions(+), 49 deletions(-) diff -puN drivers/ide/ide-floppy.c~ide_floppy-maybe-fix drivers/ide/ide-floppy.c --- 25/drivers/ide/ide-floppy.c~ide_floppy-maybe-fix 2003-09-02 00:28:11.000000000 -0700 +++ 25-akpm/drivers/ide/ide-floppy.c 2003-09-02 00:28:11.000000000 -0700 @@ -156,7 +156,6 @@ typedef struct idefloppy_packet_command_ int request_transfer; /* Bytes to transfer */ int actually_transferred; /* Bytes actually transferred */ int buffer_size; /* Size of our data buffer */ - char *b_data; /* Pointer which runs on the buffers */ int b_count; /* Missing/Available data on the current buffer */ struct request *rq; /* The corresponding request */ u8 *buffer; /* Data buffer */ @@ -515,9 +514,6 @@ typedef struct { u8 reserved[4]; } idefloppy_mode_parameter_header_t; -#define IDEFLOPPY_MIN(a,b) ((a)<(b) ? (a):(b)) -#define IDEFLOPPY_MAX(a,b) ((a)>(b) ? (a):(b)) - /* * Too bad. The drive wants to send us data which we are not ready to accept. * Just throw it away. @@ -575,28 +571,31 @@ static int idefloppy_do_end_request(ide_ static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount) { struct request *rq = pc->rq; + struct bio_vec *bvec; struct bio *bio = rq->bio; - int count; + unsigned long flags; + char *data; + int count, i; + + rq_for_each_bio(bio, rq) { + bio_for_each_segment(bvec, bio, i) { + if (!bcount) + break; + + count = min(bvec->bv_len, bcount); + data = bvec_kmap_irq(bvec, &flags); + atapi_input_bytes(drive, data, count); + bcount -= count; + pc->b_count += count; + bvec_kunmap_irq(data, &flags); - while (bcount) { - if (pc->b_count == bio->bi_size) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_do_end_request(drive, 1, 0); - if ((bio = rq->bio) != NULL) - pc->b_count = 0; - } - if (bio == NULL) { - printk(KERN_ERR "%s: bio == NULL in " - "idefloppy_input_buffers, bcount == %d\n", - drive->name, bcount); - idefloppy_discard_data(drive, bcount); - return; - } - count = IDEFLOPPY_MIN(bio->bi_size - pc->b_count, bcount); - atapi_input_bytes(drive, bio_data(bio) + pc->b_count, count); - bcount -= count; - pc->b_count += count; + idefloppy_do_end_request(drive, 1, count >> 9); + } + } + + if (bcount) { + printk(KERN_ERR "%s: bio == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount); + idefloppy_discard_data(drive, bcount); } } @@ -604,30 +603,30 @@ static void idefloppy_output_buffers (id { struct request *rq = pc->rq; struct bio *bio = rq->bio; - int count; - - while (bcount) { - if (!pc->b_count) { - rq->sector += rq->current_nr_sectors; - rq->nr_sectors -= rq->current_nr_sectors; - idefloppy_do_end_request(drive, 1, 0); - if ((bio = rq->bio) != NULL) { - pc->b_data = bio_data(bio); - pc->b_count = bio->bi_size; - } + struct bio_vec *bvec; + unsigned long flags; + int count, i; + char *data; + + rq_for_each_bio(bio, rq) { + bio_for_each_segment(bvec, bio, i) { + if (!bcount) + break; + + count = min(bvec->bv_len, bcount); + data = bvec_kmap_irq(bvec, &flags); + atapi_output_bytes(drive, data, count); + bcount -= count; + pc->b_count += count; + bvec_kunmap_irq(data, &flags); + + idefloppy_do_end_request(drive, 1, count >> 9); } - if (bio == NULL) { - printk(KERN_ERR "%s: bio == NULL in " - "idefloppy_output_buffers, bcount == %d\n", - drive->name, bcount); - idefloppy_write_zeros(drive, bcount); - return; - } - count = IDEFLOPPY_MIN(pc->b_count, bcount); - atapi_output_bytes(drive, pc->b_data, count); - bcount -= count; - pc->b_data += count; - pc->b_count -= count; + } + + if (bio == NULL) { + printk(KERN_ERR "%s: bio == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount); + idefloppy_write_zeros(drive, bcount); } } @@ -732,7 +731,6 @@ static void idefloppy_init_pc (idefloppy pc->request_transfer = 0; pc->buffer = pc->pc_buffer; pc->buffer_size = IDEFLOPPY_PC_BUFFER_SIZE; - pc->b_data = NULL; // pc->bio = NULL; pc->callback = &idefloppy_pc_callback; } @@ -1199,7 +1197,6 @@ static void idefloppy_create_rw_cmd (ide put_unaligned(htonl(block), (unsigned int *) &pc->c[2]); pc->callback = &idefloppy_rw_callback; pc->rq = rq; - pc->b_data = rq->buffer; pc->b_count = cmd == READ ? 0 : rq->bio->bi_size; if (rq->flags & REQ_RW) set_bit(PC_WRITING, &pc->flags); _