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