aboutsummaryrefslogtreecommitdiffstats
path: root/block
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-11-15 04:51:40 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-11-15 04:51:40 -0500
commitf055408957750cf759162c364c2a4dfe19765844 (patch)
treeaecc0a13c582d310902e6fa95d8853c627828fcc /block
parent83cbd33aae2c3cd14f80a8abf733033a57aa4923 (diff)
parent4060994c3e337b40e0f6fa8ce2cc178e021baf3d (diff)
Merge branch 'master'
Diffstat (limited to 'block')
-rw-r--r--block/cfq-iosched.c58
-rw-r--r--block/elevator.c60
-rw-r--r--block/genhd.c14
-rw-r--r--block/noop-iosched.c85
4 files changed, 167 insertions, 50 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ecacca9c87..2b64f5852b 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -861,8 +861,8 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
861 * store what was left of this slice, if the queue idled out 861 * store what was left of this slice, if the queue idled out
862 * or was preempted 862 * or was preempted
863 */ 863 */
864 if (time_after(now, cfqq->slice_end)) 864 if (time_after(cfqq->slice_end, now))
865 cfqq->slice_left = now - cfqq->slice_end; 865 cfqq->slice_left = cfqq->slice_end - now;
866 else 866 else
867 cfqq->slice_left = 0; 867 cfqq->slice_left = 0;
868 868
@@ -999,7 +999,7 @@ cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
999/* 999/*
1000 * get next queue for service 1000 * get next queue for service
1001 */ 1001 */
1002static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) 1002static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd)
1003{ 1003{
1004 unsigned long now = jiffies; 1004 unsigned long now = jiffies;
1005 struct cfq_queue *cfqq; 1005 struct cfq_queue *cfqq;
@@ -1023,7 +1023,7 @@ static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
1023 */ 1023 */
1024 if (!RB_EMPTY(&cfqq->sort_list)) 1024 if (!RB_EMPTY(&cfqq->sort_list))
1025 goto keep_queue; 1025 goto keep_queue;
1026 else if (!force && cfq_cfqq_class_sync(cfqq) && 1026 else if (cfq_cfqq_class_sync(cfqq) &&
1027 time_before(now, cfqq->slice_end)) { 1027 time_before(now, cfqq->slice_end)) {
1028 if (cfq_arm_slice_timer(cfqd, cfqq)) 1028 if (cfq_arm_slice_timer(cfqd, cfqq))
1029 return NULL; 1029 return NULL;
@@ -1092,6 +1092,42 @@ __cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1092} 1092}
1093 1093
1094static int 1094static int
1095cfq_forced_dispatch_cfqqs(struct list_head *list)
1096{
1097 int dispatched = 0;
1098 struct cfq_queue *cfqq, *next;
1099 struct cfq_rq *crq;
1100
1101 list_for_each_entry_safe(cfqq, next, list, cfq_list) {
1102 while ((crq = cfqq->next_crq)) {
1103 cfq_dispatch_insert(cfqq->cfqd->queue, crq);
1104 dispatched++;
1105 }
1106 BUG_ON(!list_empty(&cfqq->fifo));
1107 }
1108 return dispatched;
1109}
1110
1111static int
1112cfq_forced_dispatch(struct cfq_data *cfqd)
1113{
1114 int i, dispatched = 0;
1115
1116 for (i = 0; i < CFQ_PRIO_LISTS; i++)
1117 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->rr_list[i]);
1118
1119 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->busy_rr);
1120 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->cur_rr);
1121 dispatched += cfq_forced_dispatch_cfqqs(&cfqd->idle_rr);
1122
1123 cfq_slice_expired(cfqd, 0);
1124
1125 BUG_ON(cfqd->busy_queues);
1126
1127 return dispatched;
1128}
1129
1130static int
1095cfq_dispatch_requests(request_queue_t *q, int force) 1131cfq_dispatch_requests(request_queue_t *q, int force)
1096{ 1132{
1097 struct cfq_data *cfqd = q->elevator->elevator_data; 1133 struct cfq_data *cfqd = q->elevator->elevator_data;
@@ -1100,7 +1136,10 @@ cfq_dispatch_requests(request_queue_t *q, int force)
1100 if (!cfqd->busy_queues) 1136 if (!cfqd->busy_queues)
1101 return 0; 1137 return 0;
1102 1138
1103 cfqq = cfq_select_queue(cfqd, force); 1139 if (unlikely(force))
1140 return cfq_forced_dispatch(cfqd);
1141
1142 cfqq = cfq_select_queue(cfqd);
1104 if (cfqq) { 1143 if (cfqq) {
1105 int max_dispatch; 1144 int max_dispatch;
1106 1145
@@ -1115,12 +1154,9 @@ cfq_dispatch_requests(request_queue_t *q, int force)
1115 cfq_clear_cfqq_wait_request(cfqq); 1154 cfq_clear_cfqq_wait_request(cfqq);
1116 del_timer(&cfqd->idle_slice_timer); 1155 del_timer(&cfqd->idle_slice_timer);
1117 1156
1118 if (!force) { 1157 max_dispatch = cfqd->cfq_quantum;
1119 max_dispatch = cfqd->cfq_quantum; 1158 if (cfq_class_idle(cfqq))
1120 if (cfq_class_idle(cfqq)) 1159 max_dispatch = 1;
1121 max_dispatch = 1;
1122 } else
1123 max_dispatch = INT_MAX;
1124 1160
1125 return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); 1161 return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1126 } 1162 }
diff --git a/block/elevator.c b/block/elevator.c
index d4a49a3df8..e4c58827bb 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -155,9 +155,10 @@ static void elevator_setup_default(void)
155 /* 155 /*
156 * If the given scheduler is not available, fall back to no-op. 156 * If the given scheduler is not available, fall back to no-op.
157 */ 157 */
158 if (!(e = elevator_find(chosen_elevator))) 158 if ((e = elevator_find(chosen_elevator)))
159 elevator_put(e);
160 else
159 strcpy(chosen_elevator, "noop"); 161 strcpy(chosen_elevator, "noop");
160 elevator_put(e);
161} 162}
162 163
163static int __init elevator_setup(char *str) 164static int __init elevator_setup(char *str)
@@ -190,14 +191,14 @@ int elevator_init(request_queue_t *q, char *name)
190 191
191 eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL); 192 eq = kmalloc(sizeof(struct elevator_queue), GFP_KERNEL);
192 if (!eq) { 193 if (!eq) {
193 elevator_put(e->elevator_type); 194 elevator_put(e);
194 return -ENOMEM; 195 return -ENOMEM;
195 } 196 }
196 197
197 ret = elevator_attach(q, e, eq); 198 ret = elevator_attach(q, e, eq);
198 if (ret) { 199 if (ret) {
199 kfree(eq); 200 kfree(eq);
200 elevator_put(e->elevator_type); 201 elevator_put(e);
201 } 202 }
202 203
203 return ret; 204 return ret;
@@ -225,6 +226,7 @@ void elv_dispatch_sort(request_queue_t *q, struct request *rq)
225 226
226 if (q->last_merge == rq) 227 if (q->last_merge == rq)
227 q->last_merge = NULL; 228 q->last_merge = NULL;
229 q->nr_sorted--;
228 230
229 boundary = q->end_sector; 231 boundary = q->end_sector;
230 232
@@ -283,6 +285,7 @@ void elv_merge_requests(request_queue_t *q, struct request *rq,
283 285
284 if (e->ops->elevator_merge_req_fn) 286 if (e->ops->elevator_merge_req_fn)
285 e->ops->elevator_merge_req_fn(q, rq, next); 287 e->ops->elevator_merge_req_fn(q, rq, next);
288 q->nr_sorted--;
286 289
287 q->last_merge = rq; 290 q->last_merge = rq;
288} 291}
@@ -314,6 +317,20 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
314 __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); 317 __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0);
315} 318}
316 319
320static void elv_drain_elevator(request_queue_t *q)
321{
322 static int printed;
323 while (q->elevator->ops->elevator_dispatch_fn(q, 1))
324 ;
325 if (q->nr_sorted == 0)
326 return;
327 if (printed++ < 10) {
328 printk(KERN_ERR "%s: forced dispatching is broken "
329 "(nr_sorted=%u), please report this\n",
330 q->elevator->elevator_type->elevator_name, q->nr_sorted);
331 }
332}
333
317void __elv_add_request(request_queue_t *q, struct request *rq, int where, 334void __elv_add_request(request_queue_t *q, struct request *rq, int where,
318 int plug) 335 int plug)
319{ 336{
@@ -348,9 +365,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
348 365
349 case ELEVATOR_INSERT_BACK: 366 case ELEVATOR_INSERT_BACK:
350 rq->flags |= REQ_SOFTBARRIER; 367 rq->flags |= REQ_SOFTBARRIER;
351 368 elv_drain_elevator(q);
352 while (q->elevator->ops->elevator_dispatch_fn(q, 1))
353 ;
354 list_add_tail(&rq->queuelist, &q->queue_head); 369 list_add_tail(&rq->queuelist, &q->queue_head);
355 /* 370 /*
356 * We kick the queue here for the following reasons. 371 * We kick the queue here for the following reasons.
@@ -369,6 +384,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
369 case ELEVATOR_INSERT_SORT: 384 case ELEVATOR_INSERT_SORT:
370 BUG_ON(!blk_fs_request(rq)); 385 BUG_ON(!blk_fs_request(rq));
371 rq->flags |= REQ_SORTED; 386 rq->flags |= REQ_SORTED;
387 q->nr_sorted++;
372 if (q->last_merge == NULL && rq_mergeable(rq)) 388 if (q->last_merge == NULL && rq_mergeable(rq))
373 q->last_merge = rq; 389 q->last_merge = rq;
374 /* 390 /*
@@ -525,33 +541,19 @@ int elv_queue_empty(request_queue_t *q)
525 541
526struct request *elv_latter_request(request_queue_t *q, struct request *rq) 542struct request *elv_latter_request(request_queue_t *q, struct request *rq)
527{ 543{
528 struct list_head *next;
529
530 elevator_t *e = q->elevator; 544 elevator_t *e = q->elevator;
531 545
532 if (e->ops->elevator_latter_req_fn) 546 if (e->ops->elevator_latter_req_fn)
533 return e->ops->elevator_latter_req_fn(q, rq); 547 return e->ops->elevator_latter_req_fn(q, rq);
534
535 next = rq->queuelist.next;
536 if (next != &q->queue_head && next != &rq->queuelist)
537 return list_entry_rq(next);
538
539 return NULL; 548 return NULL;
540} 549}
541 550
542struct request *elv_former_request(request_queue_t *q, struct request *rq) 551struct request *elv_former_request(request_queue_t *q, struct request *rq)
543{ 552{
544 struct list_head *prev;
545
546 elevator_t *e = q->elevator; 553 elevator_t *e = q->elevator;
547 554
548 if (e->ops->elevator_former_req_fn) 555 if (e->ops->elevator_former_req_fn)
549 return e->ops->elevator_former_req_fn(q, rq); 556 return e->ops->elevator_former_req_fn(q, rq);
550
551 prev = rq->queuelist.prev;
552 if (prev != &q->queue_head && prev != &rq->queuelist)
553 return list_entry_rq(prev);
554
555 return NULL; 557 return NULL;
556} 558}
557 559
@@ -691,13 +693,15 @@ static void elevator_switch(request_queue_t *q, struct elevator_type *new_e)
691 693
692 set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags); 694 set_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
693 695
694 while (q->elevator->ops->elevator_dispatch_fn(q, 1)) 696 elv_drain_elevator(q);
695 ;
696 697
697 while (q->rq.elvpriv) { 698 while (q->rq.elvpriv) {
699 blk_remove_plug(q);
700 q->request_fn(q);
698 spin_unlock_irq(q->queue_lock); 701 spin_unlock_irq(q->queue_lock);
699 msleep(10); 702 msleep(10);
700 spin_lock_irq(q->queue_lock); 703 spin_lock_irq(q->queue_lock);
704 elv_drain_elevator(q);
701 } 705 }
702 706
703 spin_unlock_irq(q->queue_lock); 707 spin_unlock_irq(q->queue_lock);
@@ -744,13 +748,15 @@ error:
744ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) 748ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count)
745{ 749{
746 char elevator_name[ELV_NAME_MAX]; 750 char elevator_name[ELV_NAME_MAX];
751 size_t len;
747 struct elevator_type *e; 752 struct elevator_type *e;
748 753
749 memset(elevator_name, 0, sizeof(elevator_name)); 754 elevator_name[sizeof(elevator_name) - 1] = '\0';
750 strncpy(elevator_name, name, sizeof(elevator_name)); 755 strncpy(elevator_name, name, sizeof(elevator_name) - 1);
756 len = strlen(elevator_name);
751 757
752 if (elevator_name[strlen(elevator_name) - 1] == '\n') 758 if (len && elevator_name[len - 1] == '\n')
753 elevator_name[strlen(elevator_name) - 1] = '\0'; 759 elevator_name[len - 1] = '\0';
754 760
755 e = elevator_get(elevator_name); 761 e = elevator_get(elevator_name);
756 if (!e) { 762 if (!e) {
diff --git a/block/genhd.c b/block/genhd.c
index 54aec4a1ae..f04609d553 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -391,12 +391,14 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page)
391 "%8u %8u %8llu %8u " 391 "%8u %8u %8llu %8u "
392 "%8u %8u %8u" 392 "%8u %8u %8u"
393 "\n", 393 "\n",
394 disk_stat_read(disk, ios[0]), disk_stat_read(disk, merges[0]), 394 disk_stat_read(disk, ios[READ]),
395 (unsigned long long)disk_stat_read(disk, sectors[0]), 395 disk_stat_read(disk, merges[READ]),
396 jiffies_to_msecs(disk_stat_read(disk, ticks[0])), 396 (unsigned long long)disk_stat_read(disk, sectors[READ]),
397 disk_stat_read(disk, ios[1]), disk_stat_read(disk, merges[1]), 397 jiffies_to_msecs(disk_stat_read(disk, ticks[READ])),
398 (unsigned long long)disk_stat_read(disk, sectors[1]), 398 disk_stat_read(disk, ios[WRITE]),
399 jiffies_to_msecs(disk_stat_read(disk, ticks[1])), 399 disk_stat_read(disk, merges[WRITE]),
400 (unsigned long long)disk_stat_read(disk, sectors[WRITE]),
401 jiffies_to_msecs(disk_stat_read(disk, ticks[WRITE])),
400 disk->in_flight, 402 disk->in_flight,
401 jiffies_to_msecs(disk_stat_read(disk, io_ticks)), 403 jiffies_to_msecs(disk_stat_read(disk, io_ticks)),
402 jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); 404 jiffies_to_msecs(disk_stat_read(disk, time_in_queue)));
diff --git a/block/noop-iosched.c b/block/noop-iosched.c
index e54f006e7e..f370e4a7fe 100644
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -7,21 +7,94 @@
7#include <linux/module.h> 7#include <linux/module.h>
8#include <linux/init.h> 8#include <linux/init.h>
9 9
10static void elevator_noop_add_request(request_queue_t *q, struct request *rq) 10struct noop_data {
11 struct list_head queue;
12};
13
14static void noop_merged_requests(request_queue_t *q, struct request *rq,
15 struct request *next)
16{
17 list_del_init(&next->queuelist);
18}
19
20static int noop_dispatch(request_queue_t *q, int force)
21{
22 struct noop_data *nd = q->elevator->elevator_data;
23
24 if (!list_empty(&nd->queue)) {
25 struct request *rq;
26 rq = list_entry(nd->queue.next, struct request, queuelist);
27 list_del_init(&rq->queuelist);
28 elv_dispatch_sort(q, rq);
29 return 1;
30 }
31 return 0;
32}
33
34static void noop_add_request(request_queue_t *q, struct request *rq)
35{
36 struct noop_data *nd = q->elevator->elevator_data;
37
38 list_add_tail(&rq->queuelist, &nd->queue);
39}
40
41static int noop_queue_empty(request_queue_t *q)
11{ 42{
12 rq->flags |= REQ_NOMERGE; 43 struct noop_data *nd = q->elevator->elevator_data;
13 elv_dispatch_add_tail(q, rq); 44
45 return list_empty(&nd->queue);
46}
47
48static struct request *
49noop_former_request(request_queue_t *q, struct request *rq)
50{
51 struct noop_data *nd = q->elevator->elevator_data;
52
53 if (rq->queuelist.prev == &nd->queue)
54 return NULL;
55 return list_entry(rq->queuelist.prev, struct request, queuelist);
56}
57
58static struct request *
59noop_latter_request(request_queue_t *q, struct request *rq)
60{
61 struct noop_data *nd = q->elevator->elevator_data;
62
63 if (rq->queuelist.next == &nd->queue)
64 return NULL;
65 return list_entry(rq->queuelist.next, struct request, queuelist);
14} 66}
15 67
16static int elevator_noop_dispatch(request_queue_t *q, int force) 68static int noop_init_queue(request_queue_t *q, elevator_t *e)
17{ 69{
70 struct noop_data *nd;
71
72 nd = kmalloc(sizeof(*nd), GFP_KERNEL);
73 if (!nd)
74 return -ENOMEM;
75 INIT_LIST_HEAD(&nd->queue);
76 e->elevator_data = nd;
18 return 0; 77 return 0;
19} 78}
20 79
80static void noop_exit_queue(elevator_t *e)
81{
82 struct noop_data *nd = e->elevator_data;
83
84 BUG_ON(!list_empty(&nd->queue));
85 kfree(nd);
86}
87
21static struct elevator_type elevator_noop = { 88static struct elevator_type elevator_noop = {
22 .ops = { 89 .ops = {
23 .elevator_dispatch_fn = elevator_noop_dispatch, 90 .elevator_merge_req_fn = noop_merged_requests,
24 .elevator_add_req_fn = elevator_noop_add_request, 91 .elevator_dispatch_fn = noop_dispatch,
92 .elevator_add_req_fn = noop_add_request,
93 .elevator_queue_empty_fn = noop_queue_empty,
94 .elevator_former_req_fn = noop_former_request,
95 .elevator_latter_req_fn = noop_latter_request,
96 .elevator_init_fn = noop_init_queue,
97 .elevator_exit_fn = noop_exit_queue,
25 }, 98 },
26 .elevator_name = "noop", 99 .elevator_name = "noop",
27 .elevator_owner = THIS_MODULE, 100 .elevator_owner = THIS_MODULE,