diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/as-iosched.c | 6 | ||||
-rw-r--r-- | block/cfq-iosched.c | 60 | ||||
-rw-r--r-- | block/deadline-iosched.c | 2 | ||||
-rw-r--r-- | block/elevator.c | 62 | ||||
-rw-r--r-- | block/genhd.c | 14 | ||||
-rw-r--r-- | block/ll_rw_blk.c | 2 | ||||
-rw-r--r-- | block/noop-iosched.c | 85 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 45 |
8 files changed, 198 insertions, 78 deletions
diff --git a/block/as-iosched.c b/block/as-iosched.c index a78e160..43fa204 100644 --- a/block/as-iosched.c +++ b/block/as-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/as-iosched.c - * * Anticipatory & deadline i/o scheduler. * * Copyright (C) 2002 Jens Axboe <axboe@suse.de> @@ -1373,10 +1371,6 @@ static void as_add_request(request_queue_t *q, struct request *rq) struct as_rq *alias; int data_dir; - if (arq->state != AS_RQ_PRESCHED) { - printk("arq->state: %d\n", arq->state); - WARN_ON(1); - } arq->state = AS_RQ_NEW; if (rq_data_dir(arq->request) == READ diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ecacca9..ee0bb41 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/cfq-iosched.c - * * CFQ, or complete fairness queueing, disk scheduler. * * Based on ideas from a previously unfinished io @@ -861,8 +859,8 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, * store what was left of this slice, if the queue idled out * or was preempted */ - if (time_after(now, cfqq->slice_end)) - cfqq->slice_left = now - cfqq->slice_end; + if (time_after(cfqq->slice_end, now)) + cfqq->slice_left = cfqq->slice_end - now; else cfqq->slice_left = 0; @@ -999,7 +997,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq) /* * get next queue for service */ -static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) +static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd) { unsigned long now = jiffies; struct cfq_queue *cfqq; @@ -1023,7 +1021,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) */ if (!RB_EMPTY(&cfqq->sort_list)) goto keep_queue; - else if (!force && cfq_cfqq_class_sync(cfqq) && + else if (cfq_cfqq_class_sync(cfqq) && time_before(now, cfqq->slice_end)) { if (cfq_arm_slice_timer(cfqd, cfqq)) return NULL; @@ -1092,6 +1090,42 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq, } static int +cfq_forced_dispatch_cfqqs(struct list_head *list) +{ + int dispatched = 0; + struct cfq_queue *cfqq, *next; + struct cfq_rq *crq; + + list_for_each_entry_safe(cfqq, next, list, cfq_list) { + while ((crq = cfqq->next_crq)) { + cfq_dispatch_insert(cfqq->cfqd->queue, crq); + dispatched++; + } + BUG_ON(!list_empty(&cfqq->fifo)); + } + return dispatched; +} + +static int +cfq_forced_dispatch(struct cfq_data *cfqd) +{ + int i, dispatched = 0; + + for (i = 0; i < CFQ_PRIO_LISTS; i++) + dispatched += cfq_forced_dispatch_cfqqs(&cfqd->rr_list[i]); + + dispatched += cfq_forced_dispatch_cfqqs(&cfqd->busy_rr); + dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr); + dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr); + + cfq_slice_expired(cfqd, 0); + + BUG_ON(cfqd->busy_queues); + + return dispatched; +} + +static int cfq_dispatch_requests(request_queue_t *q, int force) { struct cfq_data *cfqd = q->elevator->elevator_data; @@ -1100,7 +1134,10 @@ cfq_dispatch_requests(request_queue_t *q, int force) if (!cfqd->busy_queues) return 0; - cfqq = cfq_select_queue(cfqd, force); + if (unlikely(force)) + return cfq_forced_dispatch(cfqd); + + cfqq = cfq_select_queue(cfqd); if (cfqq) { int max_dispatch; @@ -1115,12 +1152,9 @@ cfq_dispatch_requests(request_queue_t *q, int force) cfq_clear_cfqq_wait_request(cfqq); del_timer(&cfqd->idle_slice_timer); - if (!force) { - max_dispatch = cfqd->cfq_quantum; - if (cfq_class_idle(cfqq)) - max_dispatch = 1; - } else - max_dispatch = INT_MAX; + max_dispatch = cfqd->cfq_quantum; + if (cfq_class_idle(cfqq)) + max_dispatch = 1; return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); } diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 7929471..9cbec09 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/deadline-iosched.c - * * Deadline i/o scheduler. * * Copyright (C) 2002 Jens Axboe <axboe@suse.de> diff --git a/block/elevator.c b/block/elevator.c index d4a49a3..6c3fc8a 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/elevator.c - * * Block device elevator/IO-scheduler. * * Copyright (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE @@ -155,9 +153,10 @@ static void elevator_setup_default(void) /* * If the given scheduler is not available, fall back to no-op. */ - if (!(e = elevator_find(chosen_elevator))) + if ((e = elevator_find(chosen_elevator))) + elevator_put(e); + else strcpy(chosen_elevator, "noop"); - elevator_put(e); } static int __init elevator_setup(char *str) @@ -190,14 +189,14 @@ int elevator_init(request_queue_t *q, char *name) eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); if (!eq) { - elevator_put(e->elevator_type); + elevator_put(e); return -ENOMEM; } ret = elevator_attach(q, e, eq); if (ret) { kfree(eq); - elevator_put(e->elevator_type); + elevator_put(e); } return ret; @@ -225,6 +224,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq) if (q->last_merge == rq) q->last_merge = NULL; + q->nr_sorted--; boundary = q->end_sector; @@ -283,6 +283,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq, if (e->ops->elevator_merge_req_fn) e->ops->elevator_merge_req_fn(q, rq, next); + q->nr_sorted--; q->last_merge = rq; } @@ -314,6 +315,20 @@ void elv_requeue_request(request_queue_t *q, struct request *rq) __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); } +static void elv_drain_elevator(request_queue_t *q) +{ + static int printed; + while (q->elevator->ops->elevator_dispatch_fn(q, 1)) + ; + if (q->nr_sorted == 0) + return; + if (printed++ < 10) { + printk(KERN_ERR "%s: forced dispatching is broken " + "(nr_sorted=%u), please report this\n", + q->elevator->elevator_type->elevator_name, q->nr_sorted); + } +} + void __elv_add_request(request_queue_t *q, struct request *rq, int where, int plug) { @@ -348,9 +363,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, case ELEVATOR_INSERT_BACK: rq->flags |= REQ_SOFTBARRIER; - - while (q->elevator->ops->elevator_dispatch_fn(q, 1)) - ; + elv_drain_elevator(q); list_add_tail(&rq->queuelist, &q->queue_head); /* * We kick the queue here for the following reasons. @@ -369,6 +382,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where, case ELEVATOR_INSERT_SORT: BUG_ON(!blk_fs_request(rq)); rq->flags |= REQ_SORTED; + q->nr_sorted++; if (q->last_merge == NULL && rq_mergeable(rq)) q->last_merge = rq; /* @@ -525,33 +539,19 @@ int elv_queue_empty(request_queue_t *q) struct request *elv_latter_request(request_queue_t *q, struct request *rq) { - struct list_head *next; - elevator_t *e = q->elevator; if (e->ops->elevator_latter_req_fn) return e->ops->elevator_latter_req_fn(q, rq); - - next = rq->queuelist.next; - if (next != &q->queue_head && next != &rq->queuelist) - return list_entry_rq(next); - return NULL; } struct request *elv_former_request(request_queue_t *q, struct request *rq) { - struct list_head *prev; - elevator_t *e = q->elevator; if (e->ops->elevator_former_req_fn) return e->ops->elevator_former_req_fn(q, rq); - - prev = rq->queuelist.prev; - if (prev != &q->queue_head && prev != &rq->queuelist) - return list_entry_rq(prev); - return NULL; } @@ -691,13 +691,15 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e) set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); - while (q->elevator->ops->elevator_dispatch_fn(q, 1)) - ; + elv_drain_elevator(q); while (q->rq.elvpriv) { + blk_remove_plug(q); + q->request_fn(q); spin_unlock_irq(q->queue_lock); msleep(10); spin_lock_irq(q->queue_lock); + elv_drain_elevator(q); } spin_unlock_irq(q->queue_lock); @@ -744,13 +746,15 @@ error: ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) { char elevator_name[ELV_NAME_MAX]; + size_t len; struct elevator_type *e; - memset(elevator_name, 0, sizeof(elevator_name)); - strncpy(elevator_name, name, sizeof(elevator_name)); + elevator_name[sizeof(elevator_name) - 1] = '\0'; + strncpy(elevator_name, name, sizeof(elevator_name) - 1); + len = strlen(elevator_name); - if (elevator_name[strlen(elevator_name) - 1] == '\n') - elevator_name[strlen(elevator_name) - 1] = '\0'; + if (len && elevator_name[len - 1] == '\n') + elevator_name[len - 1] = '\0'; e = elevator_get(elevator_name); if (!e) { diff --git a/block/genhd.c b/block/genhd.c index 54aec4a..f04609d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -391,12 +391,14 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) "%8u %8u %8llu %8u " "%8u %8u %8u" "\n", - disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]), - (unsigned long long)disk_stat_read(disk, sectors[0]), - jiffies_to_msecs(disk_stat_read(disk, ticks[0])), - disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]), - (unsigned long long)disk_stat_read(disk, sectors[1]), - jiffies_to_msecs(disk_stat_read(disk, ticks[1])), + disk_stat_read(disk, ios[READ]), + disk_stat_read(disk, merges[READ]), + (unsigned long long)disk_stat_read(disk, sectors[READ]), + jiffies_to_msecs(disk_stat_read(disk, ticks[READ])), + disk_stat_read(disk, ios[WRITE]), + disk_stat_read(disk, merges[WRITE]), + (unsigned long long)disk_stat_read(disk, sectors[WRITE]), + jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])), disk->in_flight, jiffies_to_msecs(disk_stat_read(disk, io_ticks)), jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 5f52e30..99c9ca6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -1,6 +1,4 @@ /* - * linux/drivers/block/ll_rw_blk.c - * * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1994, Karl Keyte: Added support for disk statistics * Elevator latency, (C) 2000 Andrea Arcangeli <andrea@suse.de> SuSE diff --git a/block/noop-iosched.c b/block/noop-iosched.c index e54f006..f370e4a 100644 --- a/block/noop-iosched.c +++ b/block/noop-iosched.c @@ -7,21 +7,94 @@ #include <linux/module.h> #include <linux/init.h> -static void elevator_noop_add_request(request_queue_t *q, struct request *rq) +struct noop_data { + struct list_head queue; +}; + +static void noop_merged_requests(request_queue_t *q, struct request *rq, + struct request *next) +{ + list_del_init(&next->queuelist); +} + +static int noop_dispatch(request_queue_t *q, int force) +{ + struct noop_data *nd = q->elevator->elevator_data; + + if (!list_empty(&nd->queue)) { + struct request *rq; + rq = list_entry(nd->queue.next, struct request, queuelist); + list_del_init(&rq->queuelist); + elv_dispatch_sort(q, rq); + return 1; + } + return 0; +} + +static void noop_add_request(request_queue_t *q, struct request *rq) +{ + struct noop_data *nd = q->elevator->elevator_data; + + list_add_tail(&rq->queuelist, &nd->queue); +} + +static int noop_queue_empty(request_queue_t *q) { - rq->flags |= REQ_NOMERGE; - elv_dispatch_add_tail(q, rq); + struct noop_data *nd = q->elevator->elevator_data; + + return list_empty(&nd->queue); +} + +static struct request * +noop_former_request(request_queue_t *q, struct request *rq) +{ + struct noop_data *nd = q->elevator->elevator_data; + + if (rq->queuelist.prev == &nd->queue) + return NULL; + return list_entry(rq->queuelist.prev, struct request, queuelist); +} + +static struct request * +noop_latter_request(request_queue_t *q, struct request *rq) +{ + struct noop_data *nd = q->elevator->elevator_data; + + if (rq->queuelist.next == &nd->queue) + return NULL; + return list_entry(rq->queuelist.next, struct request, queuelist); } -static int elevator_noop_dispatch(request_queue_t *q, int force) +static int noop_init_queue(request_queue_t *q, elevator_t *e) { + struct noop_data *nd; + + nd = kmalloc(sizeof(*nd), GFP_KERNEL); + if (!nd) + return -ENOMEM; + INIT_LIST_HEAD(&nd->queue); + e->elevator_data = nd; return 0; } +static void noop_exit_queue(elevator_t *e) +{ + struct noop_data *nd = e->elevator_data; + + BUG_ON(!list_empty(&nd->queue)); + kfree(nd); +} + static struct elevator_type elevator_noop = { .ops = { - .elevator_dispatch_fn = elevator_noop_dispatch, - .elevator_add_req_fn = elevator_noop_add_request, + .elevator_merge_req_fn = noop_merged_requests, + .elevator_dispatch_fn = noop_dispatch, + .elevator_add_req_fn = noop_add_request, + .elevator_queue_empty_fn = noop_queue_empty, + .elevator_former_req_fn = noop_former_request, + .elevator_latter_req_fn = noop_latter_request, + .elevator_init_fn = noop_init_queue, + .elevator_exit_fn = noop_exit_queue, }, .elevator_name = "noop", .elevator_owner = THIS_MODULE, diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 382dea7..6e7db2e 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -442,11 +442,37 @@ error: return err; } + +/* Send basic block requests */ +static int __blk_send_generic(request_queue_t *q, struct gendisk *bd_disk, int cmd, int data) +{ + struct request *rq; + int err; + + rq = blk_get_request(q, WRITE, __GFP_WAIT); + rq->flags |= REQ_BLOCK_PC; + rq->data = NULL; + rq->data_len = 0; + rq->timeout = BLK_DEFAULT_TIMEOUT; + memset(rq->cmd, 0, sizeof(rq->cmd)); + rq->cmd[0] = cmd; + rq->cmd[4] = data; + rq->cmd_len = 6; + err = blk_execute_rq(q, bd_disk, rq, 0); + blk_put_request(rq); + + return err; +} + +static inline int blk_send_start_stop(request_queue_t *q, struct gendisk *bd_disk, int data) +{ + return __blk_send_generic(q, bd_disk, GPCMD_START_STOP_UNIT, data); +} + int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, void __user *arg) { request_queue_t *q; - struct request *rq; - int close = 0, err; + int err; q = bd_disk->queue; if (!q) @@ -564,19 +590,10 @@ int scsi_cmd_ioctl(struct file *file, struct gendisk *bd_disk, unsigned int cmd, err = sg_scsi_ioctl(file, q, bd_disk, arg); break; case CDROMCLOSETRAY: - close = 1; + err = blk_send_start_stop(q, bd_disk, 0x03); + break; case CDROMEJECT: - rq = blk_get_request(q, WRITE, __GFP_WAIT); - rq->flags |= REQ_BLOCK_PC; - rq->data = NULL; - rq->data_len = 0; - rq->timeout = BLK_DEFAULT_TIMEOUT; - memset(rq->cmd, 0, sizeof(rq->cmd)); - rq->cmd[0] = GPCMD_START_STOP_UNIT; - rq->cmd[4] = 0x02 + (close != 0); - rq->cmd_len = 6; - err = blk_execute_rq(q, bd_disk, rq, 0); - blk_put_request(rq); + err = blk_send_start_stop(q, bd_disk, 0x02); break; default: err = -ENOTTY; |