diff options
author | Jeff Garzik <jgarzik@pobox.com> | 2005-11-15 04:51:40 -0500 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-11-15 04:51:40 -0500 |
commit | f055408957750cf759162c364c2a4dfe19765844 (patch) | |
tree | aecc0a13c582d310902e6fa95d8853c627828fcc /block | |
parent | 83cbd33aae2c3cd14f80a8abf733033a57aa4923 (diff) | |
parent | 4060994c3e337b40e0f6fa8ce2cc178e021baf3d (diff) |
Merge branch 'master'
Diffstat (limited to 'block')
-rw-r--r-- | block/cfq-iosched.c | 58 | ||||
-rw-r--r-- | block/elevator.c | 60 | ||||
-rw-r--r-- | block/genhd.c | 14 | ||||
-rw-r--r-- | block/noop-iosched.c | 85 |
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 | */ |
1002 | static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force) | 1002 | static 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 | ||
1094 | static int | 1094 | static int |
1095 | cfq_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 | |||
1111 | static int | ||
1112 | cfq_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 | |||
1130 | static int | ||
1095 | cfq_dispatch_requests(request_queue_t *q, int force) | 1131 | cfq_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 | ||
163 | static int __init elevator_setup(char *str) | 164 | static 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 | ||
320 | static 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 | |||
317 | void __elv_add_request(request_queue_t *q, struct request *rq, int where, | 334 | void __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 | ||
526 | struct request *elv_latter_request(request_queue_t *q, struct request *rq) | 542 | struct 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 | ||
542 | struct request *elv_former_request(request_queue_t *q, struct request *rq) | 551 | struct 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: | |||
744 | ssize_t elv_iosched_store(request_queue_t *q, const char *name, size_t count) | 748 | ssize_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 | ||
10 | static void elevator_noop_add_request(request_queue_t *q, struct request *rq) | 10 | struct noop_data { |
11 | struct list_head queue; | ||
12 | }; | ||
13 | |||
14 | static void noop_merged_requests(request_queue_t *q, struct request *rq, | ||
15 | struct request *next) | ||
16 | { | ||
17 | list_del_init(&next->queuelist); | ||
18 | } | ||
19 | |||
20 | static 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 | |||
34 | static 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 | |||
41 | static 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 | |||
48 | static struct request * | ||
49 | noop_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 | |||
58 | static struct request * | ||
59 | noop_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 | ||
16 | static int elevator_noop_dispatch(request_queue_t *q, int force) | 68 | static 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 | ||
80 | static 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 | |||
21 | static struct elevator_type elevator_noop = { | 88 | static 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, |