From: Jens Axboe <axboe@suse.de>

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);

_