--- 2.3.99-pre3aa1-alpha/drivers/block/paride/pd.c.~1~	Thu Feb 17 13:57:00 2000
+++ 2.3.99-pre3aa1-alpha/drivers/block/paride/pd.c	Sat Apr  1 16:50:10 2000
@@ -880,8 +880,6 @@
 
 	bh = CURRENT->bh;
 	req = CURRENT;
-	if (bh->b_reqnext)
-		printk("%s: OUCH: b_reqnext != NULL\n",PD.name);
 
         if ((pd_dev >= PD_DEVS) || 
 	    ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {
--- 2.3.99-pre3aa1-alpha/drivers/block/paride/pf.c.~1~	Thu Feb 17 13:57:00 2000
+++ 2.3.99-pre3aa1-alpha/drivers/block/paride/pf.c	Sat Apr  1 16:50:36 2000
@@ -863,8 +863,6 @@
 
 	bh = CURRENT->bh;
 	req = CURRENT;
-	if (bh->b_reqnext)
-		printk("%s: OUCH: b_reqnext != NULL\n",PF.name);
 
         if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) {
                 end_request(0);
--- 2.3.99-pre3aa1-alpha/drivers/block/ll_rw_blk.c.~1~	Thu Mar 30 19:14:01 2000
+++ 2.3.99-pre3aa1-alpha/drivers/block/ll_rw_blk.c	Sat Apr  1 16:59:59 2000
@@ -481,7 +481,7 @@
 	elevator_merge_requests(&q->elevator, req, next);
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
-	req->nr_sectors += next->nr_sectors;
+	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
 	next->rq_status = RQ_INACTIVE;
 	list_del(&next->queue);
 	wake_up (&wait_for_request);
@@ -685,7 +685,7 @@
 				break;
 			req->bhtail->b_reqnext = bh;
 			req->bhtail = bh;
-		    	req->nr_sectors += count;
+		    	req->nr_sectors = req->hard_nr_sectors += count;
 			drive_stat_acct(req, count, 0);
 
 			elevator_merge_after(elevator, req, latency);
@@ -714,8 +714,8 @@
 		    	req->bh = bh;
 		    	req->buffer = bh->b_data;
 		    	req->current_nr_sectors = count;
-		    	req->sector = sector;
-		    	req->nr_sectors += count;
+		    	req->sector = req->hard_sector = sector;
+		    	req->nr_sectors = req->hard_nr_sectors += count;
 			drive_stat_acct(req, count, 0);
 
 			elevator_merge_before(elevator, req, latency);
@@ -754,8 +754,8 @@
 /* fill up the request-info, and add it to the queue */
 	req->cmd = rw;
 	req->errors = 0;
-	req->sector = sector;
-	req->nr_sectors = count;
+	req->hard_sector = req->sector = sector;
+	req->hard_nr_sectors = req->nr_sectors = count;
 	req->current_nr_sectors = count;
 	req->nr_segments = 1; /* Always 1 for a new request. */
 	req->nr_hw_segments = 1; /* Always 1 for a new request. */
@@ -908,36 +908,49 @@
 int end_that_request_first (struct request *req, int uptodate, char *name)
 {
 	struct buffer_head * bh;
-	int nsect;
+	int ret = 0;
 
 	req->errors = 0;
-	if (!uptodate) {
+	if (!uptodate)
 		printk("end_request: I/O error, dev %s (%s), sector %lu\n",
 			kdevname(req->rq_dev), name, req->sector);
-		if ((bh = req->bh) != NULL) {
-			nsect = bh->b_size >> 9;
-			req->nr_sectors--;
-			req->nr_sectors &= ~(nsect - 1);
-			req->sector += nsect;
-			req->sector &= ~(nsect - 1);
-		}
-	}
 
 	if ((bh = req->bh) != NULL) {
+		/*
+		 * Fixup current_nr_sectors: while it's supposed to be
+		 * _read-only_ from a lowlevel point of view, some buggy
+		 * driver is instead changing it for no good reason
+		 * (so we can't rely on it to be correct from here!).
+		 * Remove this fixup when none device driver will be
+		 * clobbering current_nr_sectors anymore.
+		 */
+		req->current_nr_sectors = bh->b_size >> 9;
+
 		req->bh = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_end_io(bh, uptodate);
 		if ((bh = req->bh) != NULL) {
-			req->current_nr_sectors = bh->b_size >> 9;
-			if (req->nr_sectors < req->current_nr_sectors) {
-				req->nr_sectors = req->current_nr_sectors;
-				printk("end_request: buffer-list destroyed\n");
-			}
+			int nsect;
+
+			nsect = req->current_nr_sectors;
+			req->hard_sector += nsect;
+			req->hard_nr_sectors -= nsect;
+
+			req->sector = req->hard_sector;
+			req->nr_sectors = req->hard_nr_sectors;
 			req->buffer = bh->b_data;
-			return 1;
+			req->current_nr_sectors = bh->b_size >> 9;
+
+			nsect = req->current_nr_sectors - 1;
+			if (req->sector & nsect || req->nr_sectors & nsect)
+				printk(KERN_ERR
+				       "end_request: sectors %lu nr_sectors %lu mask %x\n",
+				       req->sector, req->nr_sectors, nsect);
+
+			ret = 1;
 		}
 	}
-	return 0;
+	return ret;
 }
 
 void end_that_request_last(struct request *req)
--- 2.3.99-pre3aa1-alpha/include/linux/blkdev.h.~1~	Thu Mar 30 19:18:49 2000
+++ 2.3.99-pre3aa1-alpha/include/linux/blkdev.h	Sat Apr  1 17:04:24 2000
@@ -32,6 +32,7 @@
 	int errors;
 	unsigned long sector;
 	unsigned long nr_sectors;
+	unsigned long hard_sector, hard_nr_sectors;
 	unsigned int nr_segments;
 	unsigned int nr_hw_segments;
 	unsigned long current_nr_sectors;