diff -urN 2.4.0-test7/drivers/block/DAC960.c blkdev/drivers/block/DAC960.c
--- 2.4.0-test7/drivers/block/DAC960.c	Fri Aug 25 19:37:16 2000
+++ blkdev/drivers/block/DAC960.c	Fri Aug 25 19:41:06 2000
@@ -1825,7 +1825,6 @@
       Request->nr_segments < Controller->DriverScatterGatherLimit)
     {
       Request->nr_segments++;
-      RequestQueue->elevator.nr_segments++;
       return true;
     }
   return false;
@@ -1849,7 +1848,6 @@
       Request->nr_segments < Controller->DriverScatterGatherLimit)
     {
       Request->nr_segments++;
-      RequestQueue->elevator.nr_segments++;
       return true;
     }
   return false;
@@ -1879,7 +1877,6 @@
   if (TotalSegments > MaxSegments ||
       TotalSegments > Controller->DriverScatterGatherLimit)
     return false;
-  RequestQueue->elevator.nr_segments -= SameSegment;
   Request->nr_segments = TotalSegments;
   return true;
 }
diff -urN 2.4.0-test7/drivers/block/elevator.c blkdev/drivers/block/elevator.c
--- 2.4.0-test7/drivers/block/elevator.c	Fri Aug 25 19:37:16 2000
+++ blkdev/drivers/block/elevator.c	Fri Aug 25 19:41:06 2000
@@ -51,50 +51,67 @@
 }
 
 int elevator_linus_merge(request_queue_t *q, struct request **req,
+			 struct list_head * head,
 			 struct buffer_head *bh, int rw,
-			 int *max_sectors, int *max_segments)
+			 int max_sectors, int max_segments)
 {
-	struct list_head *entry, *head = &q->queue_head;
+	struct list_head *entry;
 	unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
+	int front = 0, back = 0;
 
-	entry = head;
-	if (q->head_active && !q->plugged)
-		head = head->next;
-
-	while ((entry = entry->prev) != head) {
+	entry = &q->queue_head;
+	while ((entry = entry->prev) != head && !back && !front) {
 		struct request *__rq = *req = blkdev_entry_to_request(entry);
-		if (__rq->sem)
-			continue;
+
 		if (__rq->cmd != rw)
 			continue;
-		if (__rq->nr_sectors + count > *max_sectors)
-			continue;
 		if (__rq->rq_dev != bh->b_rdev)
 			continue;
-		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+		if (__rq->sector + __rq->nr_sectors == bh->b_rsector)
+			back = 1;
+		else if (__rq->sector - count == bh->b_rsector)
+			front = 1;
+
+		if (__rq->nr_sectors + count > max_sectors)
+			continue;
+		if (__rq->sem)
+			continue;
+
+		if (back) {
 			ret = ELEVATOR_BACK_MERGE;
 			break;
 		}
 		if (!__rq->elevator_sequence)
 			break;
-		if (__rq->sector - count == bh->b_rsector) {
-			__rq->elevator_sequence--;
+		if (front) {
 			ret = ELEVATOR_FRONT_MERGE;
 			break;
 		}
 	}
 
+	return ret;
+}
+
+void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int ret, int front)
+{
+	struct list_head *entry = &req->queue, *head = &q->queue_head;
+
+	if (front)
+		req->elevator_sequence--;
+
 	/*
 	 * second pass scan of requests that got passed over, if any
 	 */
-	if (ret != ELEVATOR_NO_MERGE && *req) {
-		while ((entry = entry->next) != &q->queue_head) {
-			struct request *tmp = blkdev_entry_to_request(entry);
-			tmp->elevator_sequence--;
-		}
+	while ((entry = entry->next) != head) {
+		struct request *tmp = blkdev_entry_to_request(entry);
+		tmp->elevator_sequence--;
 	}
+}
 
-	return ret;
+void elevator_linus_merge_req(struct request *req, struct request *next)
+{
+	if (next->elevator_sequence < req->elevator_sequence)
+		req->elevator_sequence = next->elevator_sequence;
 }
 
 /*
@@ -111,38 +128,43 @@
  * See if we can find a request that is buffer can be coalesced with.
  */
 int elevator_noop_merge(request_queue_t *q, struct request **req,
+			struct list_head * head,
 			struct buffer_head *bh, int rw,
-			int *max_sectors, int *max_segments)
+			int max_sectors, int max_segments)
 {
-	struct list_head *entry, *head = &q->queue_head;
+	struct list_head *entry;
 	unsigned int count = bh->b_size >> 9;
+	int back = 0, front = 0;
 
-	if (q->head_active && !q->plugged)
-		head = head->next;
-
-	entry = head;
-	while ((entry = entry->prev) != head) {
+	entry = &q->queue_head;
+	while ((entry = entry->prev) != head && !back && !front) {
 		struct request *__rq = *req = blkdev_entry_to_request(entry);
-		if (__rq->sem)
-			continue;
+
 		if (__rq->cmd != rw)
 			continue;
-		if (__rq->nr_sectors + count > *max_sectors)
-			continue;
 		if (__rq->rq_dev != bh->b_rdev)
 			continue;
 		if (__rq->sector + __rq->nr_sectors == bh->b_rsector)
+			back = 1;
+		else if (__rq->sector - count == bh->b_rsector)
+			front = 1;
+
+		if (__rq->nr_sectors + count > max_sectors)
+			continue;
+		if (__rq->sem)
+			continue;
+
+		if (back)
 			return ELEVATOR_BACK_MERGE;
-		if (__rq->sector - count == bh->b_rsector)
+		if (front)
 			return ELEVATOR_FRONT_MERGE;
 	}
 	return ELEVATOR_NO_MERGE;
 }
 
-/*
- * The noop "elevator" does not do any accounting
- */
-void elevator_noop_dequeue(struct request *req) {}
+void elevator_noop_merge_cleanup(request_queue_t *q, struct request *req, int ret, int front) {}
+
+void elevator_noop_merge_req(struct request *req, struct request *next) {}
 
 int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
 {
diff -urN 2.4.0-test7/drivers/block/ll_rw_blk.c blkdev/drivers/block/ll_rw_blk.c
--- 2.4.0-test7/drivers/block/ll_rw_blk.c	Fri Aug 25 19:37:16 2000
+++ blkdev/drivers/block/ll_rw_blk.c	Fri Aug 25 19:41:06 2000
@@ -280,7 +280,6 @@
 {
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -317,7 +316,6 @@
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
@@ -645,6 +643,7 @@
 	if(!(q->merge_requests_fn)(q, req, next, max_segments))
 		return;
 
+	q->elevator.elevator_merge_req_fn(req, next);
 	req->bhtail->b_reqnext = next->bh;
 	req->bhtail = next->bhtail;
 	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
@@ -733,27 +732,27 @@
 	 */
 	spin_lock_irq(&io_request_lock);
 
+	if (list_empty(head)) {
+		q->plug_device_fn(q, bh->b_rdev); /* is atomic */
+		goto get_rq;
+	}
+
 	/*
 	 * skip first entry, for devices with active queue head
 	 */
 	if (q->head_active && !q->plugged)
 		head = head->next;
 
-	if (list_empty(head)) {
-		q->plug_device_fn(q, bh->b_rdev); /* is atomic */
-		goto get_rq;
-	}
-
-	el_ret = elevator->elevator_merge_fn(q, &req, bh, rw, &max_sectors, &max_segments);
+	el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw, max_sectors, max_segments);
 	switch (el_ret) {
 
 		case ELEVATOR_BACK_MERGE:
 			if (!q->back_merge_fn(q, req, bh, max_segments))
 				break;
+			elevator->elevator_merge_cleanup_fn(q, req, el_ret, 0);
 			req->bhtail->b_reqnext = bh;
 			req->bhtail = bh;
 			req->nr_sectors = req->hard_nr_sectors += count;
-			req->e = elevator;
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
 			attempt_back_merge(q, req, max_sectors, max_segments);
 			goto out;
@@ -761,13 +760,13 @@
 		case ELEVATOR_FRONT_MERGE:
 			if (!q->front_merge_fn(q, req, bh, max_segments))
 				break;
+			elevator->elevator_merge_cleanup_fn(q, req, el_ret, 1);
 			bh->b_reqnext = req->bh;
 			req->bh = bh;
 			req->buffer = bh->b_data;
 			req->current_nr_sectors = count;
 			req->sector = req->hard_sector = sector;
 			req->nr_sectors = req->hard_nr_sectors += count;
-			req->e = elevator;
 			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
 			attempt_front_merge(q, head, req, max_sectors, max_segments);
 			goto out;
@@ -817,11 +816,8 @@
 	req->bh = bh;
 	req->bhtail = bh;
 	req->rq_dev = bh->b_rdev;
-	req->e = elevator;
 	add_request(q, req, head, latency);
 out:
-	if (!q->plugged)
-		(q->request_fn)(q);
 	spin_unlock_irq(&io_request_lock);
 	return 0;
 end_io:
@@ -1016,10 +1012,6 @@
 
 void end_that_request_last(struct request *req)
 {
-	if (req->e) {
-		printk("end_that_request_last called with non-dequeued req\n");
-		BUG();
-	}
 	if (req->sem != NULL)
 		up(req->sem);
 
diff -urN 2.4.0-test7/drivers/block/lvm.c blkdev/drivers/block/lvm.c
--- 2.4.0-test7/drivers/block/lvm.c	Thu Jul 20 21:31:02 2000
+++ blkdev/drivers/block/lvm.c	Fri Aug 25 19:41:06 2000
@@ -195,7 +195,7 @@
 #define	DEVICE_REQUEST	lvm_dummy_device_request
 
 static int lvm_make_request_fn(request_queue_t *, int, struct buffer_head*);
-static void lvm_plug_device_noop(request_queue_t *, kdev_t);
+static void lvm_dummy_plug_device(request_queue_t *, kdev_t);
 
 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
 static int lvm_blk_open(struct inode *, struct file *);
@@ -394,7 +394,7 @@
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_make_request_fn);
-	blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_plug_device_noop);
+	blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), lvm_dummy_plug_device);
 	/* optional read root VGDA */
 /*
    if ( *rootvg != 0) vg_read_with_pv_and_lv ( rootvg, &vg);
@@ -1482,11 +1482,18 @@
 }
 
 /*
- * plug device function is a noop because plugging has to happen
- * in the queue of the physical blockdevice to allow the
- * elevator to do a better job.
+ * plugging has to happen in the queue of the physical blockdevice
+ * to allow the elevator to do a better job.
  */
-static void lvm_plug_device_noop(request_queue_t *q, kdev_t dev) { }
+static void lvm_dummy_plug_device(request_queue_t *q, kdev_t dev)
+{
+	printk(KERN_EMERG
+	       "%s -- oops, got lvm plug for %02d:%02d [sector: %lu]\n",
+	       lvm_name,
+	       MAJOR(CURRENT->rq_dev),
+	       MINOR(CURRENT->rq_dev),
+	       CURRENT->sector);
+}
 
 /********************************************************************
  *
diff -urN 2.4.0-test7/drivers/i2o/i2o_block.c blkdev/drivers/i2o/i2o_block.c
--- 2.4.0-test7/drivers/i2o/i2o_block.c	Tue Jul 11 03:50:23 2000
+++ blkdev/drivers/i2o/i2o_block.c	Fri Aug 25 19:41:06 2000
@@ -392,7 +392,6 @@
 
 	if (req->nr_segments < max_segments) {
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	}
 	return 0;
@@ -436,7 +435,6 @@
 	if (total_segments > max_segments)
 		return 0;
 
-	q->elevator.nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
diff -urN 2.4.0-test7/drivers/ide/ide-dma.c blkdev/drivers/ide/ide-dma.c
--- 2.4.0-test7/drivers/ide/ide-dma.c	Fri Jul 28 07:24:10 2000
+++ blkdev/drivers/ide/ide-dma.c	Fri Aug 25 19:41:06 2000
@@ -224,6 +224,9 @@
 		unsigned char *virt_addr = bh->b_data;
 		unsigned int size = bh->b_size;
 
+		if (nents >= PRD_ENTRIES)
+			return 0;
+
 		while ((bh = bh->b_reqnext) != NULL) {
 			if ((virt_addr + size) != (unsigned char *) bh->b_data)
 				break;
@@ -266,7 +269,7 @@
 		cur_len = sg_dma_len(sg);
 
 		while (cur_len) {
-			if (++count >= PRD_ENTRIES) {
+			if (count++ >= PRD_ENTRIES) {
 				printk("%s: DMA table too small\n", drive->name);
 				pci_unmap_sg(HWIF(drive)->pci_dev,
 					     HWIF(drive)->sg_table,
diff -urN 2.4.0-test7/drivers/ide/ide-probe.c blkdev/drivers/ide/ide-probe.c
--- 2.4.0-test7/drivers/ide/ide-probe.c	Thu Aug 17 19:57:28 2000
+++ blkdev/drivers/ide/ide-probe.c	Fri Aug 25 21:39:59 2000
@@ -761,9 +761,10 @@
 	for (unit = 0; unit < minors; ++unit) {
 		*bs++ = BLOCK_SIZE;
 #ifdef CONFIG_BLK_DEV_PDC4030
-		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : MAX_SECTORS);
+		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 256);
 #else
-		*max_sect++ = MAX_SECTORS;
+		/* IDE can do up to 128K per request. */
+		*max_sect++ = 256;
 #endif
 		*max_ra++ = MAX_READAHEAD;
 	}
diff -urN 2.4.0-test7/drivers/scsi/scsi_merge.c blkdev/drivers/scsi/scsi_merge.c
--- 2.4.0-test7/drivers/scsi/scsi_merge.c	Thu Apr 27 17:56:40 2000
+++ blkdev/drivers/scsi/scsi_merge.c	Fri Aug 25 19:41:06 2000
@@ -324,7 +324,6 @@
 	    req->nr_segments >= SHpnt->sg_tablesize)
 		return 0;
 	req->nr_segments++;
-	q->elevator.nr_segments++;
 	return 1;
 }
 
@@ -341,11 +340,8 @@
 	if (req->nr_hw_segments >= SHpnt->sg_tablesize ||
 	     req->nr_segments >= SHpnt->sg_tablesize)
 		return 0;
-	if (req->nr_segments >= max_segments)
-		return 0;
 	req->nr_hw_segments++;
 	req->nr_segments++;
-	q->elevator.nr_segments++;
 	return 1;
 }
 #else
@@ -361,7 +357,6 @@
 		 * counter.
 		 */
 		req->nr_segments++;
-		q->elevator.nr_segments++;
 		return 1;
 	} else {
 		return 0;
@@ -417,8 +412,10 @@
 	SDpnt = (Scsi_Device *) q->queuedata;
 	SHpnt = SDpnt->host;
 
+#ifdef DMA_CHUNK_SIZE
 	if (max_segments > 64)
 		max_segments = 64;
+#endif
 
 	if (use_clustering) {
 		/* 
@@ -471,8 +468,10 @@
 	SDpnt = (Scsi_Device *) q->queuedata;
 	SHpnt = SDpnt->host;
 
+#ifdef DMA_CHUNK_SIZE
 	if (max_segments > 64)
 		max_segments = 64;
+#endif
 
 	if (use_clustering) {
 		/* 
@@ -601,10 +600,10 @@
 	SDpnt = (Scsi_Device *) q->queuedata;
 	SHpnt = SDpnt->host;
 
+#ifdef DMA_CHUNK_SIZE
 	if (max_segments > 64)
 		max_segments = 64;
 
-#ifdef DMA_CHUNK_SIZE
 	/* If it would not fit into prepared memory space for sg chain,
 	 * then don't allow the merge.
 	 */
@@ -664,7 +663,6 @@
 			 * This one is OK.  Let it go.
 			 */
 			req->nr_segments += next->nr_segments - 1;
-			q->elevator.nr_segments--;
 #ifdef DMA_CHUNK_SIZE
 			req->nr_hw_segments += next->nr_hw_segments - 1;
 #endif
diff -urN 2.4.0-test7/include/linux/blk.h blkdev/include/linux/blk.h
--- 2.4.0-test7/include/linux/blk.h	Sun Aug 20 14:58:25 2000
+++ blkdev/include/linux/blk.h	Fri Aug 25 19:41:06 2000
@@ -87,10 +87,6 @@
 
 static inline void blkdev_dequeue_request(struct request * req)
 {
-	if (req->e) {
-		req->e->dequeue_fn(req);
-		req->e = NULL;
-	}
 	list_del(&req->queue);
 }
 
diff -urN 2.4.0-test7/include/linux/blkdev.h blkdev/include/linux/blkdev.h
--- 2.4.0-test7/include/linux/blkdev.h	Sun Aug 20 14:58:25 2000
+++ blkdev/include/linux/blkdev.h	Fri Aug 25 19:41:06 2000
@@ -47,7 +47,6 @@
 	struct buffer_head * bh;
 	struct buffer_head * bhtail;
 	request_queue_t *q;
-	elevator_t *e;
 };
 
 #include <linux/elevator.h>
@@ -175,9 +174,8 @@
 
 extern int * max_segments[MAX_BLKDEV];
 
-#define MAX_SECTORS 254
-
-#define MAX_SEGMENTS MAX_SECTORS
+#define MAX_SECTORS 128
+#define MAX_SEGMENTS (MAX_SECTORS*8)
 
 #define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
 
diff -urN 2.4.0-test7/include/linux/elevator.h blkdev/include/linux/elevator.h
--- 2.4.0-test7/include/linux/elevator.h	Fri Jul 28 07:24:15 2000
+++ blkdev/include/linux/elevator.h	Fri Aug 25 19:41:06 2000
@@ -7,34 +7,35 @@
 			    struct list_head *,
 			    struct list_head *, int);
 
-typedef int (elevator_merge_fn) (request_queue_t *, struct request **,
-				 struct buffer_head *, int, int *, int *);
+typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct list_head *,
+				 struct buffer_head *, int, int, int);
 
-typedef void (elevator_dequeue_fn) (struct request *);
+typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int, int);
+
+typedef void (elevator_merge_req_fn) (struct request *, struct request *);
 
 struct elevator_s
 {
-	int sequence;
-
 	int read_latency;
 	int write_latency;
-	int max_bomb_segments;
-
-	unsigned int nr_segments;
-	int read_pendings;
 
 	elevator_fn * elevator_fn;
 	elevator_merge_fn *elevator_merge_fn;
-	elevator_dequeue_fn *dequeue_fn;
+	elevator_merge_cleanup_fn *elevator_merge_cleanup_fn;
+	elevator_merge_req_fn *elevator_merge_req_fn;
 
 	unsigned int queue_ID;
 };
 
 void elevator_noop(struct request *, elevator_t *, struct list_head *, struct list_head *, int);
-int elevator_noop_merge(request_queue_t *, struct request **, struct buffer_head *, int, int *, int *);
-void elevator_noop_dequeue(struct request *);
+int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int);
+void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int, int);
+void elevator_noop_merge_req(struct request *, struct request *);
+
 void elevator_linus(struct request *, elevator_t *, struct list_head *, struct list_head *, int);
-int elevator_linus_merge(request_queue_t *, struct request **, struct buffer_head *, int, int *, int *);
+int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int);
+void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int, int);
+void elevator_linus_merge_req(struct request *, struct request *);
 
 typedef struct blkelv_ioctl_arg_s {
 	int queue_ID;
@@ -80,36 +81,26 @@
 	return latency;
 }
 
-#define ELEVATOR_NOOP						\
-((elevator_t) {							\
-	0,				/* sequence */		\
-								\
-	0,				/* read_latency */	\
-	0,				/* write_latency */	\
-	0,				/* max_bomb_segments */	\
-								\
-	0,				/* nr_segments */	\
-	0,				/* read_pendings */	\
-								\
-	elevator_noop,			/* elevator_fn */	\
-	elevator_noop_merge,		/* elevator_merge_fn */ \
-	elevator_noop_dequeue,		/* dequeue_fn */	\
+#define ELEVATOR_NOOP							\
+((elevator_t) {								\
+	0,				/* read_latency */		\
+	0,				/* write_latency */		\
+									\
+	elevator_noop,			/* elevator_fn */		\
+	elevator_noop_merge,		/* elevator_merge_fn */		\
+	elevator_noop_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
+	elevator_noop_merge_req,	/* elevator_merge_req_fn */	\
 	})
 
-#define ELEVATOR_LINUS						\
-((elevator_t) {							\
-	0,				/* not used */		\
-								\
-	1000000,				/* read passovers */	\
-	2000000,				/* write passovers */	\
-	0,				/* max_bomb_segments */	\
-								\
-	0,				/* not used */		\
-	0,				/* not used */		\
-								\
-	elevator_linus,			/* elevator_fn */	\
-	elevator_linus_merge,		/* elevator_merge_fn */ \
-	elevator_noop_dequeue,		/* dequeue_fn */	\
+#define ELEVATOR_LINUS							\
+((elevator_t) {								\
+	50000,				/* read passovers */		\
+	100000,				/* write passovers */		\
+									\
+	elevator_linus,			/* elevator_fn */		\
+	elevator_linus_merge,		/* elevator_merge_fn */		\
+	elevator_linus_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
+	elevator_linus_merge_req,	/* elevator_merge_req_fn */	\
 	})
 
 #endif
diff -urN 2.4.0-test7/mm/filemap.c blkdev/mm/filemap.c
--- 2.4.0-test7/mm/filemap.c	Fri Aug 25 19:37:32 2000
+++ blkdev/mm/filemap.c	Fri Aug 25 19:41:06 2000
@@ -958,10 +958,6 @@
  *   accessed sequentially.
  */
 	if (ahead) {
-		if (reada_ok == 2) {
-			run_task_queue(&tq_disk);
-		}
-
 		filp->f_ralen += ahead;
 		filp->f_rawin += filp->f_ralen;
 		filp->f_raend = raend + ahead + 1;