![[LWN Logo]](/images/lcorner.png) |
|
![[Timeline]](/images/Included.png) |
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- /opt/kernel/linux-2.4.0-test11/drivers/block/DAC960.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/block/DAC960.c Sat Nov 4 16:15:54 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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/block/elevator.c linux/drivers/block/elevator.c
--- /opt/kernel/linux-2.4.0-test11/drivers/block/elevator.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/block/elevator.c Tue Nov 21 11:18:49 2000
@@ -24,125 +24,111 @@
#include <linux/blkdev.h>
#include <linux/elevator.h>
#include <linux/blk.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
-/*
- * Order ascending, but only allow a request to be skipped a certain
- * number of times
- */
-void elevator_linus(struct request *req, elevator_t *elevator,
- struct list_head *real_head,
- struct list_head *head, int orig_latency)
-{
- struct list_head *entry = real_head;
- struct request *tmp;
-
- req->elevator_sequence = orig_latency;
-
- while ((entry = entry->prev) != head) {
- tmp = blkdev_entry_to_request(entry);
- if (IN_ORDER(tmp, req))
- break;
- if (!tmp->elevator_sequence)
- break;
- tmp->elevator_sequence--;
- }
- list_add(&req->queue, entry);
-}
-
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;
- entry = head;
- if (q->head_active && !q->plugged)
- head = head->next;
-
+ entry = &q->queue_head;
while ((entry = entry->prev) != head) {
- struct request *__rq = *req = blkdev_entry_to_request(entry);
+ struct request *__rq = blkdev_entry_to_request(entry);
+
+ /*
+ * simply "aging" of requests in queue
+ */
+ if (__rq->elevator_sequence-- <= 0)
+ break;
+
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->nr_sectors + count > max_sectors)
+ continue;
+ if (__rq->elevator_sequence < count)
+ break;
if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
ret = ELEVATOR_BACK_MERGE;
+ *req = __rq;
break;
- }
- if (!__rq->elevator_sequence)
- break;
- if (__rq->sector - count == bh->b_rsector) {
- __rq->elevator_sequence--;
+ } else if (__rq->sector - count == bh->b_rsector) {
ret = ELEVATOR_FRONT_MERGE;
+ __rq->elevator_sequence -= count;
+ *req = __rq;
break;
- }
+ } else if (BHRQ_IN_ORDER(bh, __rq) && *req == NULL)
+ *req = __rq;
}
+ return ret;
+}
+
+void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
+{
+ struct list_head *entry = &req->queue, *head = &q->queue_head;
+
/*
* 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 -= count;
}
-
- return ret;
}
-/*
- * No request sorting, just add it to the back of the list
- */
-void elevator_noop(struct request *req, elevator_t *elevator,
- struct list_head *real_head, struct list_head *head,
- int orig_latency)
+void elevator_linus_merge_req(struct request *req, struct request *next)
{
- list_add_tail(&req->queue, real_head);
+ if (next->elevator_sequence < req->elevator_sequence)
+ req->elevator_sequence = next->elevator_sequence;
}
/*
- * See if we can find a request that is buffer can be coalesced with.
+ * See if we can find a request that this 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;
- if (q->head_active && !q->plugged)
- head = head->next;
-
- entry = head;
+ entry = &q->queue_head;
while ((entry = entry->prev) != head) {
- struct request *__rq = *req = blkdev_entry_to_request(entry);
- if (__rq->sem)
- continue;
+ struct request *__rq = blkdev_entry_to_request(entry);
+
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->nr_sectors + count > max_sectors)
+ continue;
+ if (__rq->sem)
+ continue;
+ if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+ *req = __rq;
return ELEVATOR_BACK_MERGE;
- if (__rq->sector - count == bh->b_rsector)
+ } else if (__rq->sector - count == bh->b_rsector) {
+ *req = __rq;
return ELEVATOR_FRONT_MERGE;
+ }
}
+
+ *req = blkdev_entry_to_request(q->queue_head.prev);
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 count) {}
+
+void elevator_noop_merge_req(struct request *req, struct request *next) {}
int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
{
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- /opt/kernel/linux-2.4.0-test11/drivers/block/ll_rw_blk.c Mon Nov 20 12:37:20 2000
+++ linux/drivers/block/ll_rw_blk.c Mon Nov 20 14:32:28 2000
@@ -125,7 +125,7 @@
return max_sectors[MAJOR(dev)][MINOR(dev)];
}
-static inline request_queue_t *__blk_get_queue(kdev_t dev)
+inline request_queue_t *__blk_get_queue(kdev_t dev)
{
struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
@@ -153,17 +153,14 @@
static int __blk_cleanup_queue(struct list_head *head)
{
- struct list_head *entry;
struct request *rq;
int i = 0;
if (list_empty(head))
return 0;
- entry = head->next;
do {
- rq = list_entry(entry, struct request, table);
- entry = entry->next;
+ rq = list_entry(head->next, struct request, table);
list_del(&rq->table);
kmem_cache_free(request_cachep, rq);
i++;
@@ -191,6 +188,8 @@
count -= __blk_cleanup_queue(&q->request_freelist[READ]);
count -= __blk_cleanup_queue(&q->request_freelist[WRITE]);
+ count -= __blk_cleanup_queue(&q->pending_freelist[READ]);
+ count -= __blk_cleanup_queue(&q->pending_freelist[WRITE]);
if (count)
printk("blk_cleanup_queue: leaked requests (%d)\n", count);
@@ -280,7 +279,6 @@
{
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -317,7 +315,6 @@
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
@@ -353,7 +350,7 @@
}
}
-static void generic_unplug_device(void *data)
+void generic_unplug_device(void *data)
{
request_queue_t *q = (request_queue_t *) data;
unsigned long flags;
@@ -368,13 +365,18 @@
struct request *rq;
int i;
+ INIT_LIST_HEAD(&q->request_freelist[READ]);
+ INIT_LIST_HEAD(&q->request_freelist[WRITE]);
+ INIT_LIST_HEAD(&q->pending_freelist[READ]);
+ INIT_LIST_HEAD(&q->pending_freelist[WRITE]);
+ q->pending_free[READ] = q->pending_free[WRITE] = 0;
+
/*
- * Divide requests in half between read and write. This used to
- * be a 2/3 advantage for reads, but now reads can steal from
- * the write free list.
+ * Divide requests in half between read and write
*/
for (i = 0; i < QUEUE_NR_REQUESTS; i++) {
rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
+ memset(rq, 0, sizeof(struct request));
rq->rq_status = RQ_INACTIVE;
list_add(&rq->table, &q->request_freelist[i & 1]);
}
@@ -413,15 +415,13 @@
* blk_queue_headactive().
*
* Note:
- * blk_init_queue() must be paired with a blk_cleanup-queue() call
+ * blk_init_queue() must be paired with a blk_cleanup_queue() call
* when the block device is deactivated (such as at module unload).
**/
static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
{
INIT_LIST_HEAD(&q->queue_head);
- INIT_LIST_HEAD(&q->request_freelist[READ]);
- INIT_LIST_HEAD(&q->request_freelist[WRITE]);
elevator_init(&q->elevator, ELEVATOR_LINUS);
blk_init_free_list(q);
q->request_fn = rfn;
@@ -443,7 +443,6 @@
q->head_active = 1;
}
-
#define blkdev_free_rq(list) list_entry((list)->next, struct request, table);
/*
* Get a free request. io_request_lock must be held and interrupts
@@ -451,37 +450,16 @@
*/
static inline struct request *get_request(request_queue_t *q, int rw)
{
- struct list_head *list = &q->request_freelist[rw];
- struct request *rq;
-
- /*
- * Reads get preferential treatment and are allowed to steal
- * from the write free list if necessary.
- */
- if (!list_empty(list)) {
- rq = blkdev_free_rq(list);
- goto got_rq;
- }
+ struct request *rq = NULL;
- /*
- * if the WRITE list is non-empty, we know that rw is READ
- * and that the READ list is empty. allow reads to 'steal'
- * from the WRITE list.
- */
- if (!list_empty(&q->request_freelist[WRITE])) {
- list = &q->request_freelist[WRITE];
- rq = blkdev_free_rq(list);
- goto got_rq;
+ if (!list_empty(&q->request_freelist[rw])) {
+ rq = blkdev_free_rq(&q->request_freelist[rw]);
+ list_del(&rq->table);
+ rq->rq_status = RQ_ACTIVE;
+ rq->special = NULL;
+ rq->q = q;
}
- return NULL;
-
-got_rq:
- list_del(&rq->table);
- rq->free_list = list;
- rq->rq_status = RQ_ACTIVE;
- rq->special = NULL;
- rq->q = q;
return rq;
}
@@ -578,16 +556,22 @@
*/
static inline void add_request(request_queue_t * q, struct request * req,
- struct list_head *head, int lat)
+ struct list_head *insert_here)
{
int major;
drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1);
+ if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
+ spin_unlock_irq(&io_request_lock);
+ BUG();
+ }
+
/*
- * let selected elevator insert the request
+ * elevator indicated where it wants this request to be
+ * inserted at elevator_merge time
*/
- q->elevator.elevator_fn(req, &q->elevator, &q->queue_head, head, lat);
+ list_add(&req->queue, insert_here);
/*
* FIXME(eric) I don't understand why there is a need for this
@@ -605,20 +589,47 @@
(q->request_fn)(q);
}
+void inline blk_refill_freelist(request_queue_t *q, int rw)
+{
+ if (q->pending_free[rw]) {
+ list_splice(&q->pending_freelist[rw], &q->request_freelist[rw]);
+ INIT_LIST_HEAD(&q->pending_freelist[rw]);
+ q->pending_free[rw] = 0;
+ }
+}
+
/*
* Must be called with io_request_lock held and interrupts disabled
*/
void inline blkdev_release_request(struct request *req)
{
+ request_queue_t *q = req->q;
+ int rw = req->cmd;
+
req->rq_status = RQ_INACTIVE;
+ req->q = NULL;
/*
* Request may not have originated from ll_rw_blk
*/
- if (req->free_list) {
- list_add(&req->table, req->free_list);
- req->free_list = NULL;
- wake_up(&req->q->wait_for_request);
+ if (q) {
+ if (!list_empty(&q->request_freelist[rw])) {
+ blk_refill_freelist(q, rw);
+ list_add(&req->table, &q->request_freelist[rw]);
+ return;
+ }
+
+ /*
+ * free list is empty, add to pending free list and
+ * batch wakeups
+ */
+ list_add(&req->table, &q->pending_freelist[rw]);
+
+ if (++q->pending_free[rw] >= (QUEUE_NR_REQUESTS >> 3)) {
+ int wake_up = q->pending_free[rw];
+ blk_refill_freelist(q, rw);
+ wake_up_nr(&q->wait_for_request, wake_up);
+ }
}
}
@@ -643,9 +654,10 @@
* will have been updated to the appropriate number,
* and we shouldn't do it here too.
*/
- if(!(q->merge_requests_fn)(q, req, next, max_segments))
+ 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;
@@ -683,8 +695,8 @@
unsigned int sector, count;
int max_segments = MAX_SEGMENTS;
struct request * req = NULL, *freereq = NULL;
- int rw_ahead, max_sectors, el_ret;
- struct list_head *head = &q->queue_head;
+ int rw_ahead, max_sectors, el_ret, rw_cmd = rw;
+ struct list_head *head, *insert_here;
int latency;
elevator_t *elevator = &q->elevator;
@@ -695,9 +707,10 @@
switch (rw) {
case READA:
rw_ahead = 1;
- rw = READ; /* drop into READ */
+ rw_cmd = rw = READ; /* drop into READ */
case READ:
case WRITE:
+ latency = elevator_request_latency(elevator, rw);
break;
default:
BUG();
@@ -726,36 +739,31 @@
*/
max_sectors = get_max_sectors(bh->b_rdev);
- latency = elevator_request_latency(elevator, rw);
-
+again:
/*
* Now we acquire the request spinlock, we have to be mega careful
* not to schedule or do something nonatomic
*/
-again:
spin_lock_irq(&io_request_lock);
- /*
- * skip first entry, for devices with active queue head
- */
- if (q->head_active && !q->plugged)
- head = head->next;
-
+ head = &q->queue_head;
+ insert_here = head->prev;
if (list_empty(head)) {
q->plug_device_fn(q, bh->b_rdev); /* is atomic */
goto get_rq;
- }
+ } else if (q->head_active && !q->plugged)
+ head = head->next;
- 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, count);
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;
@@ -763,20 +771,28 @@
case ELEVATOR_FRONT_MERGE:
if (!q->front_merge_fn(q, req, bh, max_segments))
break;
+ elevator->elevator_merge_cleanup_fn(q, req, count);
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;
+
/*
* elevator says don't/can't merge. get new request
*/
case ELEVATOR_NO_MERGE:
+ /*
+ * use elevator hints as to where to insert the
+ * request. if no hints, just add it to the back
+ * of the queue
+ */
+ if (req)
+ insert_here = &req->queue;
break;
default:
@@ -804,7 +820,8 @@
}
/* fill up the request-info, and add it to the queue */
- req->cmd = rw;
+ req->elevator_sequence = latency;
+ req->cmd = rw_cmd;
req->errors = 0;
req->hard_sector = req->sector = sector;
req->hard_nr_sectors = req->nr_sectors = count;
@@ -816,13 +833,12 @@
req->bh = bh;
req->bhtail = bh;
req->rq_dev = bh->b_rdev;
- req->e = elevator;
- add_request(q, req, head, latency);
+ add_request(q, req, insert_here);
out:
- if (!q->plugged)
- (q->request_fn)(q);
if (freereq)
blkdev_release_request(freereq);
+ if (!q->plugged)
+ q->request_fn(q);
spin_unlock_irq(&io_request_lock);
return 0;
end_io:
@@ -877,7 +893,6 @@
buffer_IO_error(bh);
break;
}
-
}
while (q->make_request_fn(q, rw, bh));
}
@@ -995,6 +1010,8 @@
if ((bh = req->bh) != NULL) {
nsect = bh->b_size >> 9;
req->bh = bh->b_reqnext;
+ if (req->bh && (bh->b_rsector + (bh->b_size >> 9)) != req->bh->b_rsector)
+ printk("%s: %lu is followed by %lu\n", name, bh->b_rsector, req->bh->b_rsector);
bh->b_reqnext = NULL;
bh->b_end_io(bh, uptodate);
if ((bh = req->bh) != NULL) {
@@ -1017,10 +1034,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);
@@ -1158,9 +1171,11 @@
EXPORT_SYMBOL(end_that_request_last);
EXPORT_SYMBOL(blk_init_queue);
EXPORT_SYMBOL(blk_get_queue);
+EXPORT_SYMBOL(__blk_get_queue);
EXPORT_SYMBOL(blk_cleanup_queue);
EXPORT_SYMBOL(blk_queue_headactive);
EXPORT_SYMBOL(blk_queue_pluggable);
EXPORT_SYMBOL(blk_queue_make_request);
EXPORT_SYMBOL(generic_make_request);
EXPORT_SYMBOL(blkdev_release_request);
+EXPORT_SYMBOL(generic_unplug_device);
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- /opt/kernel/linux-2.4.0-test11/drivers/block/paride/pd.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/block/paride/pd.c Sat Nov 4 16:15:54 2000
@@ -392,7 +392,6 @@
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -432,7 +431,6 @@
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- /opt/kernel/linux-2.4.0-test11/drivers/block/paride/pf.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/block/paride/pf.c Sat Nov 4 16:15:54 2000
@@ -346,7 +346,6 @@
if (req->nr_segments < max_segments) {
req->nr_segments++;
- q->elevator.nr_segments++;
return 1;
}
return 0;
@@ -386,7 +385,6 @@
if (total_segments > max_segments)
return 0;
- q->elevator.nr_segments -= same_segment;
req->nr_segments = total_segments;
return 1;
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- /opt/kernel/linux-2.4.0-test11/drivers/i2o/i2o_block.c Mon Nov 20 12:37:20 2000
+++ linux/drivers/i2o/i2o_block.c Fri Nov 10 03:10:35 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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-disk.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/ide/ide-disk.c Sat Nov 4 16:40:59 2000
@@ -293,7 +293,6 @@
static ide_startstop_t multwrite_intr (ide_drive_t *drive)
{
byte stat;
- int i;
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct request *rq = &hwgroup->wrq;
@@ -309,21 +308,8 @@
ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
return ide_started;
}
- } else {
- /*
- * If the copy has all the blocks completed then
- * we can end the original request.
- */
- if (!rq->nr_sectors) { /* all done? */
- rq = hwgroup->rq;
- for (i = rq->nr_sectors; i > 0;){
- i -= rq->current_nr_sectors;
- ide_end_request(1, hwgroup);
- }
- return ide_stopped;
- }
}
- return ide_stopped; /* the original code did this here (?) */
+ return ide_stopped;
}
return ide_error(drive, "multwrite_intr", stat);
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-dma.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/ide/ide-dma.c Sat Nov 4 16:15:54 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;
@@ -257,6 +260,9 @@
HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+ if (!i)
+ return 0;
+
sg = HWIF(drive)->sg_table;
while (i && sg_dma_len(sg)) {
u32 cur_addr;
@@ -266,7 +272,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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- /opt/kernel/linux-2.4.0-test11/drivers/ide/ide-probe.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/ide/ide-probe.c Mon Nov 6 11:27:53 2000
@@ -134,7 +134,7 @@
break;
}
#endif
- printk ("CDROM");
+ printk ("CD/DVD-ROM");
break;
case ide_tape:
printk ("TAPE");
@@ -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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/md/lvm.c linux/drivers/md/lvm.c
--- /opt/kernel/linux-2.4.0-test11/drivers/md/lvm.c Mon Nov 20 12:37:20 2000
+++ linux/drivers/md/lvm.c Fri Nov 10 03:10:35 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 *);
@@ -404,7 +404,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);
@@ -1493,11 +1493,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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- /opt/kernel/linux-2.4.0-test11/drivers/scsi/scsi_lib.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/scsi/scsi_lib.c Sun Nov 19 16:35:00 2000
@@ -50,6 +50,54 @@
* This entire source file deals with the new queueing code.
*/
+/*
+ * Function: __scsi_insert_special()
+ *
+ * Purpose: worker for scsi_insert_special_*()
+ *
+ * Arguments: q - request queue where request should be inserted
+ * rq - request to be inserted
+ * data - private data
+ * at_head - insert request at head or tail of queue
+ *
+ * Lock status: Assumed that io_request_lock is not held upon entry.
+ *
+ * Returns: Nothing
+ *
+ * Notes: Makes no guarentee as to when the request will be executed.
+ * Requests stored at the end of queue are guarenteed not to
+ * be resorted and postponed.
+ */
+static void __scsi_insert_special(request_queue_t *q, struct request *rq,
+ void *data, int at_head)
+{
+ unsigned long flags;
+
+ ASSERT_LOCK(&io_request_lock, 0);
+
+ rq->cmd = SPECIAL;
+ rq->special = data;
+ rq->q = NULL;
+ rq->nr_segments = 0;
+ rq->elevator_sequence = 0;
+
+ /*
+ * We have the option of inserting the head or the tail of the queue.
+ * Typically we use the tail for new ioctls and so forth. We use the
+ * head of the queue for things like a QUEUE_FULL message from a
+ * device, or a host that is unable to accept a particular command.
+ */
+ spin_lock_irqsave(&io_request_lock, flags);
+ q->plug_device_fn(q, 0);
+
+ if (at_head)
+ list_add(&rq->queue, &q->queue_head);
+ else
+ list_add_tail(&rq->queue, &q->queue_head);
+
+ spin_unlock_irqrestore(&io_request_lock, flags);
+}
+
/*
* Function: scsi_insert_special_cmd()
@@ -73,52 +121,9 @@
*/
int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head)
{
- unsigned long flags;
- request_queue_t *q;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
- * The SCpnt already contains a request structure - we will doctor the
- * thing up with the appropriate values and use that in the actual
- * request queue.
- */
- q = &SCpnt->device->request_queue;
- SCpnt->request.cmd = SPECIAL;
- SCpnt->request.special = (void *) SCpnt;
- SCpnt->request.q = NULL;
- SCpnt->request.free_list = NULL;
- SCpnt->request.nr_segments = 0;
-
- /*
- * We have the option of inserting the head or the tail of the queue.
- * Typically we use the tail for new ioctls and so forth. We use the
- * head of the queue for things like a QUEUE_FULL message from a
- * device, or a host that is unable to accept a particular command.
- */
- spin_lock_irqsave(&io_request_lock, flags);
-
- if (at_head) {
- list_add(&SCpnt->request.queue, &q->queue_head);
- } else {
- /*
- * FIXME(eric) - we always insert at the tail of the
- * list. Otherwise ioctl commands would always take
- * precedence over normal I/O. An ioctl on a busy
- * disk might be delayed indefinitely because the
- * request might not float high enough in the queue
- * to be scheduled.
- */
- list_add_tail(&SCpnt->request.queue, &q->queue_head);
- }
+ request_queue_t *q = &SCpnt->device->request_queue;
- /*
- * Now hit the requeue function for the queue. If the host is
- * already busy, so be it - we have nothing special to do. If
- * the host can queue it, then send it off.
- */
- q->request_fn(q);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ __scsi_insert_special(q, &SCpnt->request, SCpnt, at_head);
return 0;
}
@@ -144,51 +149,9 @@
*/
int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head)
{
- unsigned long flags;
- request_queue_t *q;
-
- ASSERT_LOCK(&io_request_lock, 0);
-
- /*
- * The SCpnt already contains a request structure - we will doctor the
- * thing up with the appropriate values and use that in the actual
- * request queue.
- */
- q = &SRpnt->sr_device->request_queue;
- SRpnt->sr_request.cmd = SPECIAL;
- SRpnt->sr_request.special = (void *) SRpnt;
- SRpnt->sr_request.q = NULL;
- SRpnt->sr_request.nr_segments = 0;
-
- /*
- * We have the option of inserting the head or the tail of the queue.
- * Typically we use the tail for new ioctls and so forth. We use the
- * head of the queue for things like a QUEUE_FULL message from a
- * device, or a host that is unable to accept a particular command.
- */
- spin_lock_irqsave(&io_request_lock, flags);
+ request_queue_t *q = &SRpnt->sr_device->request_queue;
- if (at_head) {
- list_add(&SRpnt->sr_request.queue, &q->queue_head);
- } else {
- /*
- * FIXME(eric) - we always insert at the tail of the
- * list. Otherwise ioctl commands would always take
- * precedence over normal I/O. An ioctl on a busy
- * disk might be delayed indefinitely because the
- * request might not float high enough in the queue
- * to be scheduled.
- */
- list_add_tail(&SRpnt->sr_request.queue, &q->queue_head);
- }
-
- /*
- * Now hit the requeue function for the queue. If the host is
- * already busy, so be it - we have nothing special to do. If
- * the host can queue it, then send it off.
- */
- q->request_fn(q);
- spin_unlock_irqrestore(&io_request_lock, flags);
+ __scsi_insert_special(q, &SRpnt->sr_request, SRpnt, at_head);
return 0;
}
@@ -896,10 +859,11 @@
|| (SHpnt->host_blocked)
|| (SHpnt->host_self_blocked)) {
/*
- * If we are unable to process any commands at all for this
- * device, then we consider it to be starved. What this means
- * is that there are no outstanding commands for this device
- * and hence we need a little help getting it started again
+ * If we are unable to process any commands at all for
+ * this device, then we consider it to be starved.
+ * What this means is that there are no outstanding
+ * commands for this device and hence we need a
+ * little help getting it started again
* once the host isn't quite so busy.
*/
if (SDpnt->device_busy == 0) {
@@ -1000,8 +964,8 @@
}
/*
* If so, we are ready to do something. Bump the count
- * while the queue is locked and then break out of the loop.
- * Otherwise loop around and try another request.
+ * while the queue is locked and then break out of the
+ * loop. Otherwise loop around and try another request.
*/
if (!SCpnt) {
break;
@@ -1029,8 +993,9 @@
memcpy(&SCpnt->request, req, sizeof(struct request));
/*
- * We have copied the data out of the request block - it is now in
- * a field in SCpnt. Release the request block.
+ * We have copied the data out of the request block -
+ * it is now in a field in SCpnt. Release the request
+ * block.
*/
blkdev_release_request(req);
}
@@ -1047,12 +1012,14 @@
/*
* This will do a couple of things:
* 1) Fill in the actual SCSI command.
- * 2) Fill in any other upper-level specific fields (timeout).
+ * 2) Fill in any other upper-level specific fields
+ * (timeout).
*
- * If this returns 0, it means that the request failed (reading
- * past end of disk, reading offline device, etc). This won't
- * actually talk to the device, but some kinds of consistency
- * checking may cause the request to be rejected immediately.
+ * If this returns 0, it means that the request failed
+ * (reading past end of disk, reading offline device,
+ * etc). This won't actually talk to the device, but
+ * some kinds of consistency checking may cause the
+ * request to be rejected immediately.
*/
if (STpnt == NULL) {
STpnt = scsi_get_request_dev(req);
@@ -1103,8 +1070,8 @@
scsi_dispatch_cmd(SCpnt);
/*
- * Now we need to grab the lock again. We are about to mess with
- * the request queue and try to find another command.
+ * Now we need to grab the lock again. We are about to mess
+ * with the request queue and try to find another command.
*/
spin_lock_irq(&io_request_lock);
}
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- /opt/kernel/linux-2.4.0-test11/drivers/scsi/scsi_merge.c Sun Nov 19 15:27:14 2000
+++ linux/drivers/scsi/scsi_merge.c Mon Nov 20 14:44:03 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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/include/linux/blk.h linux/include/linux/blk.h
--- /opt/kernel/linux-2.4.0-test11/include/linux/blk.h Mon Nov 20 12:37:22 2000
+++ linux/include/linux/blk.h Mon Nov 20 12:39:04 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 -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/include/linux/blkdev.h linux/include/linux/blkdev.h
--- /opt/kernel/linux-2.4.0-test11/include/linux/blkdev.h Sun Nov 19 15:27:14 2000
+++ linux/include/linux/blkdev.h Mon Nov 20 12:39:04 2000
@@ -23,8 +23,6 @@
int elevator_sequence;
struct list_head table;
- struct list_head *free_list;
-
volatile int rq_status; /* should split this into a few status bits */
#define RQ_INACTIVE (-1)
#define RQ_ACTIVE 1
@@ -47,7 +45,6 @@
struct buffer_head * bh;
struct buffer_head * bhtail;
request_queue_t *q;
- elevator_t *e;
};
#include <linux/elevator.h>
@@ -77,6 +74,8 @@
* the queue request freelist, one for reads and one for writes
*/
struct list_head request_freelist[2];
+ struct list_head pending_freelist[2];
+ int pending_free[2];
/*
* Together with queue_head for cacheline sharing
@@ -152,6 +151,7 @@
extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
extern void generic_make_request(int rw, struct buffer_head * bh);
extern request_queue_t *blk_get_queue(kdev_t dev);
+extern inline request_queue_t *__blk_get_queue(kdev_t dev);
extern void blkdev_release_request(struct request *);
/*
@@ -162,6 +162,7 @@
extern void blk_queue_headactive(request_queue_t *, int);
extern void blk_queue_pluggable(request_queue_t *, plug_device_fn *);
extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
+extern void generic_unplug_device(void *);
extern int * blk_size[MAX_BLKDEV];
@@ -175,9 +176,8 @@
extern int * max_segments[MAX_BLKDEV];
-#define MAX_SECTORS 254
-
-#define MAX_SEGMENTS MAX_SECTORS
+#define MAX_SEGMENTS 128
+#define MAX_SECTORS (MAX_SEGMENTS*8)
#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/include/linux/elevator.h linux/include/linux/elevator.h
--- /opt/kernel/linux-2.4.0-test11/include/linux/elevator.h Sun Nov 19 15:27:14 2000
+++ linux/include/linux/elevator.h Sat Nov 4 16:15:55 2000
@@ -7,34 +7,32 @@
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);
+
+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 *);
-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_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);
+void elevator_noop_merge_req(struct request *, struct request *);
+
+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);
+void elevator_linus_merge_req(struct request *, struct request *);
typedef struct blkelv_ioctl_arg_s {
int queue_ID;
@@ -69,6 +67,10 @@
(s1)->sector < (s2)->sector)) || \
(s1)->rq_dev < (s2)->rq_dev)
+#define BHRQ_IN_ORDER(bh, rq) \
+ (((bh)->b_rdev == (rq)->rq_dev && \
+ (bh)->b_rsector < (rq)->sector))
+
static inline int elevator_request_latency(elevator_t * elevator, int rw)
{
int latency;
@@ -80,36 +82,24 @@
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_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) { \
+ 8192, /* read passovers */ \
+ 16384, /* write passovers */ \
+ \
+ elevator_linus_merge, /* elevator_merge_fn */ \
+ elevator_linus_merge_cleanup, /* elevator_merge_cleanup_fn */ \
+ elevator_linus_merge_req, /* elevator_merge_req_fn */ \
})
#endif
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/include/linux/sched.h linux/include/linux/sched.h
--- /opt/kernel/linux-2.4.0-test11/include/linux/sched.h Mon Nov 20 12:37:22 2000
+++ linux/include/linux/sched.h Mon Nov 20 12:39:04 2000
@@ -534,8 +534,8 @@
#define CURRENT_TIME (xtime.tv_sec)
-extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, unsigned int wq_mode));
-extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, unsigned int wq_mode));
+extern void FASTCALL(__wake_up(wait_queue_head_t *q, unsigned int mode, int nr));
+extern void FASTCALL(__wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr));
extern void FASTCALL(sleep_on(wait_queue_head_t *q));
extern long FASTCALL(sleep_on_timeout(wait_queue_head_t *q,
signed long timeout));
@@ -544,12 +544,16 @@
signed long timeout));
extern void FASTCALL(wake_up_process(struct task_struct * tsk));
-#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE,WQ_FLAG_EXCLUSIVE)
-#define wake_up_all(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE,0)
-#define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE,WQ_FLAG_EXCLUSIVE)
-#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE,WQ_FLAG_EXCLUSIVE)
-#define wake_up_interruptible_all(x) __wake_up((x),TASK_INTERRUPTIBLE,0)
-#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE,WQ_FLAG_EXCLUSIVE)
+#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
+#define wake_up_nr(x, nr) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
+#define wake_up_all(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 0)
+#define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
+#define wake_up_sync_nr(x, nr) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
+#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE, 1)
+#define wake_up_interruptible_nr(x, nr) __wake_up((x),TASK_INTERRUPTIBLE, nr)
+#define wake_up_interruptible_all(x) __wake_up((x),TASK_INTERRUPTIBLE, 0)
+#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
+#define wake_up_interruptible_sync_nr(x) __wake_up_sync((x),TASK_INTERRUPTIBLE, nr)
extern int in_group_p(gid_t);
extern int in_egroup_p(gid_t);
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/kernel/sched.c linux/kernel/sched.c
--- /opt/kernel/linux-2.4.0-test11/kernel/sched.c Mon Nov 20 12:37:22 2000
+++ linux/kernel/sched.c Sun Nov 19 15:27:04 2000
@@ -700,19 +700,15 @@
}
static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
- unsigned int wq_mode, const int sync)
+ int nr_exclusive, const int sync)
{
struct list_head *tmp, *head;
- struct task_struct *p, *best_exclusive;
+ struct task_struct *p;
unsigned long flags;
- int best_cpu, irq;
if (!q)
goto out;
- best_cpu = smp_processor_id();
- irq = in_interrupt();
- best_exclusive = NULL;
wq_write_lock_irqsave(&q->lock, flags);
#if WAITQUEUE_DEBUG
@@ -740,47 +736,27 @@
#if WAITQUEUE_DEBUG
curr->__waker = (long)__builtin_return_address(0);
#endif
- /*
- * If waking up from an interrupt context then
- * prefer processes which are affine to this
- * CPU.
- */
- if (irq && (curr->flags & wq_mode & WQ_FLAG_EXCLUSIVE)) {
- if (!best_exclusive)
- best_exclusive = p;
- if (p->processor == best_cpu) {
- best_exclusive = p;
- break;
- }
- } else {
- if (sync)
- wake_up_process_synchronous(p);
- else
- wake_up_process(p);
- if (curr->flags & wq_mode & WQ_FLAG_EXCLUSIVE)
- break;
- }
+ if (sync)
+ wake_up_process_synchronous(p);
+ else
+ wake_up_process(p);
+ if ((curr->flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
+ break;
}
}
- if (best_exclusive) {
- if (sync)
- wake_up_process_synchronous(best_exclusive);
- else
- wake_up_process(best_exclusive);
- }
wq_write_unlock_irqrestore(&q->lock, flags);
out:
return;
}
-void __wake_up(wait_queue_head_t *q, unsigned int mode, unsigned int wq_mode)
+void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
{
- __wake_up_common(q, mode, wq_mode, 0);
+ __wake_up_common(q, mode, nr, 0);
}
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, unsigned int wq_mode)
+void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)
{
- __wake_up_common(q, mode, wq_mode, 1);
+ __wake_up_common(q, mode, nr, 1);
}
#define SLEEP_ON_VAR \
diff -ur --exclude-from /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.0-test11/mm/filemap.c linux/mm/filemap.c
--- /opt/kernel/linux-2.4.0-test11/mm/filemap.c Mon Nov 20 12:37:22 2000
+++ linux/mm/filemap.c Sat Nov 18 10:12:23 2000
@@ -263,7 +263,7 @@
*/
age_page_up(page);
if (inactive_shortage() > inactive_target / 2 && free_shortage())
- wakeup_kswapd(0);
+ wakeup_kswapd(0);
not_found:
return page;
}
@@ -855,10 +855,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;