aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index d01b411c72f0..1e2aff812ee2 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -11,6 +11,7 @@
11#include <linux/elevator.h> 11#include <linux/elevator.h>
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <linux/ioprio.h> 13#include <linux/ioprio.h>
14#include <linux/blktrace_api.h>
14 15
15/* 16/*
16 * tunables 17 * tunables
@@ -41,13 +42,14 @@ static int cfq_slice_idle = HZ / 125;
41 42
42#define RQ_CIC(rq) \ 43#define RQ_CIC(rq) \
43 ((struct cfq_io_context *) (rq)->elevator_private) 44 ((struct cfq_io_context *) (rq)->elevator_private)
44#define RQ_CFQQ(rq) ((rq)->elevator_private2) 45#define RQ_CFQQ(rq) (struct cfq_queue *) ((rq)->elevator_private2)
45 46
46static struct kmem_cache *cfq_pool; 47static struct kmem_cache *cfq_pool;
47static struct kmem_cache *cfq_ioc_pool; 48static struct kmem_cache *cfq_ioc_pool;
48 49
49static DEFINE_PER_CPU(unsigned long, ioc_count); 50static DEFINE_PER_CPU(unsigned long, ioc_count);
50static struct completion *ioc_gone; 51static struct completion *ioc_gone;
52static DEFINE_SPINLOCK(ioc_gone_lock);
51 53
52#define CFQ_PRIO_LISTS IOPRIO_BE_NR 54#define CFQ_PRIO_LISTS IOPRIO_BE_NR
53#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) 55#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
@@ -155,6 +157,7 @@ struct cfq_queue {
155 unsigned short ioprio, org_ioprio; 157 unsigned short ioprio, org_ioprio;
156 unsigned short ioprio_class, org_ioprio_class; 158 unsigned short ioprio_class, org_ioprio_class;
157 159
160 pid_t pid;
158}; 161};
159 162
160enum cfqq_state_flags { 163enum cfqq_state_flags {
@@ -198,6 +201,11 @@ CFQ_CFQQ_FNS(slice_new);
198CFQ_CFQQ_FNS(sync); 201CFQ_CFQQ_FNS(sync);
199#undef CFQ_CFQQ_FNS 202#undef CFQ_CFQQ_FNS
200 203
204#define cfq_log_cfqq(cfqd, cfqq, fmt, args...) \
205 blk_add_trace_msg((cfqd)->queue, "cfq%d " fmt, (cfqq)->pid, ##args)
206#define cfq_log(cfqd, fmt, args...) \
207 blk_add_trace_msg((cfqd)->queue, "cfq " fmt, ##args)
208
201static void cfq_dispatch_insert(struct request_queue *, struct request *); 209static void cfq_dispatch_insert(struct request_queue *, struct request *);
202static struct cfq_queue *cfq_get_queue(struct cfq_data *, int, 210static struct cfq_queue *cfq_get_queue(struct cfq_data *, int,
203 struct io_context *, gfp_t); 211 struct io_context *, gfp_t);
@@ -234,8 +242,10 @@ static inline int cfq_bio_sync(struct bio *bio)
234 */ 242 */
235static inline void cfq_schedule_dispatch(struct cfq_data *cfqd) 243static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
236{ 244{
237 if (cfqd->busy_queues) 245 if (cfqd->busy_queues) {
246 cfq_log(cfqd, "schedule dispatch");
238 kblockd_schedule_work(&cfqd->unplug_work); 247 kblockd_schedule_work(&cfqd->unplug_work);
248 }
239} 249}
240 250
241static int cfq_queue_empty(struct request_queue *q) 251static int cfq_queue_empty(struct request_queue *q)
@@ -270,6 +280,7 @@ static inline void
270cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq) 280cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
271{ 281{
272 cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies; 282 cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
283 cfq_log_cfqq(cfqd, cfqq, "set_slice=%lu", cfqq->slice_end - jiffies);
273} 284}
274 285
275/* 286/*
@@ -539,6 +550,7 @@ static void cfq_resort_rr_list(struct cfq_data *cfqd, struct cfq_queue *cfqq)
539 */ 550 */
540static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) 551static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
541{ 552{
553 cfq_log_cfqq(cfqd, cfqq, "add_to_rr");
542 BUG_ON(cfq_cfqq_on_rr(cfqq)); 554 BUG_ON(cfq_cfqq_on_rr(cfqq));
543 cfq_mark_cfqq_on_rr(cfqq); 555 cfq_mark_cfqq_on_rr(cfqq);
544 cfqd->busy_queues++; 556 cfqd->busy_queues++;
@@ -552,6 +564,7 @@ static void cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
552 */ 564 */
553static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) 565static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
554{ 566{
567 cfq_log_cfqq(cfqd, cfqq, "del_from_rr");
555 BUG_ON(!cfq_cfqq_on_rr(cfqq)); 568 BUG_ON(!cfq_cfqq_on_rr(cfqq));
556 cfq_clear_cfqq_on_rr(cfqq); 569 cfq_clear_cfqq_on_rr(cfqq);
557 570
@@ -638,6 +651,8 @@ static void cfq_activate_request(struct request_queue *q, struct request *rq)
638 struct cfq_data *cfqd = q->elevator->elevator_data; 651 struct cfq_data *cfqd = q->elevator->elevator_data;
639 652
640 cfqd->rq_in_driver++; 653 cfqd->rq_in_driver++;
654 cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "activate rq, drv=%d",
655 cfqd->rq_in_driver);
641 656
642 /* 657 /*
643 * If the depth is larger 1, it really could be queueing. But lets 658 * If the depth is larger 1, it really could be queueing. But lets
@@ -657,6 +672,8 @@ static void cfq_deactivate_request(struct request_queue *q, struct request *rq)
657 672
658 WARN_ON(!cfqd->rq_in_driver); 673 WARN_ON(!cfqd->rq_in_driver);
659 cfqd->rq_in_driver--; 674 cfqd->rq_in_driver--;
675 cfq_log_cfqq(cfqd, RQ_CFQQ(rq), "deactivate rq, drv=%d",
676 cfqd->rq_in_driver);
660} 677}
661 678
662static void cfq_remove_request(struct request *rq) 679static void cfq_remove_request(struct request *rq)
@@ -746,6 +763,7 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,
746 struct cfq_queue *cfqq) 763 struct cfq_queue *cfqq)
747{ 764{
748 if (cfqq) { 765 if (cfqq) {
766 cfq_log_cfqq(cfqd, cfqq, "set_active");
749 cfqq->slice_end = 0; 767 cfqq->slice_end = 0;
750 cfq_clear_cfqq_must_alloc_slice(cfqq); 768 cfq_clear_cfqq_must_alloc_slice(cfqq);
751 cfq_clear_cfqq_fifo_expire(cfqq); 769 cfq_clear_cfqq_fifo_expire(cfqq);
@@ -763,6 +781,8 @@ static void
763__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, 781__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
764 int timed_out) 782 int timed_out)
765{ 783{
784 cfq_log_cfqq(cfqd, cfqq, "slice expired t=%d", timed_out);
785
766 if (cfq_cfqq_wait_request(cfqq)) 786 if (cfq_cfqq_wait_request(cfqq))
767 del_timer(&cfqd->idle_slice_timer); 787 del_timer(&cfqd->idle_slice_timer);
768 788
@@ -772,8 +792,10 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
772 /* 792 /*
773 * store what was left of this slice, if the queue idled/timed out 793 * store what was left of this slice, if the queue idled/timed out
774 */ 794 */
775 if (timed_out && !cfq_cfqq_slice_new(cfqq)) 795 if (timed_out && !cfq_cfqq_slice_new(cfqq)) {
776 cfqq->slice_resid = cfqq->slice_end - jiffies; 796 cfqq->slice_resid = cfqq->slice_end - jiffies;
797 cfq_log_cfqq(cfqd, cfqq, "resid=%ld", cfqq->slice_resid);
798 }
777 799
778 cfq_resort_rr_list(cfqd, cfqq); 800 cfq_resort_rr_list(cfqd, cfqq);
779 801
@@ -866,6 +888,12 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
866 return; 888 return;
867 889
868 /* 890 /*
891 * still requests with the driver, don't idle
892 */
893 if (cfqd->rq_in_driver)
894 return;
895
896 /*
869 * task has exited, don't wait 897 * task has exited, don't wait
870 */ 898 */
871 cic = cfqd->active_cic; 899 cic = cfqd->active_cic;
@@ -892,6 +920,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
892 sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT)); 920 sl = min(sl, msecs_to_jiffies(CFQ_MIN_TT));
893 921
894 mod_timer(&cfqd->idle_slice_timer, jiffies + sl); 922 mod_timer(&cfqd->idle_slice_timer, jiffies + sl);
923 cfq_log(cfqd, "arm_idle: %lu", sl);
895} 924}
896 925
897/* 926/*
@@ -902,6 +931,8 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq)
902 struct cfq_data *cfqd = q->elevator->elevator_data; 931 struct cfq_data *cfqd = q->elevator->elevator_data;
903 struct cfq_queue *cfqq = RQ_CFQQ(rq); 932 struct cfq_queue *cfqq = RQ_CFQQ(rq);
904 933
934 cfq_log_cfqq(cfqd, cfqq, "dispatch_insert");
935
905 cfq_remove_request(rq); 936 cfq_remove_request(rq);
906 cfqq->dispatched++; 937 cfqq->dispatched++;
907 elv_dispatch_sort(q, rq); 938 elv_dispatch_sort(q, rq);
@@ -931,8 +962,9 @@ static struct request *cfq_check_fifo(struct cfq_queue *cfqq)
931 rq = rq_entry_fifo(cfqq->fifo.next); 962 rq = rq_entry_fifo(cfqq->fifo.next);
932 963
933 if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) 964 if (time_before(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo]))
934 return NULL; 965 rq = NULL;
935 966
967 cfq_log_cfqq(cfqd, cfqq, "fifo=%p", rq);
936 return rq; 968 return rq;
937} 969}
938 970
@@ -1072,6 +1104,7 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)
1072 1104
1073 BUG_ON(cfqd->busy_queues); 1105 BUG_ON(cfqd->busy_queues);
1074 1106
1107 cfq_log(cfqd, "forced_dispatch=%d\n", dispatched);
1075 return dispatched; 1108 return dispatched;
1076} 1109}
1077 1110
@@ -1112,6 +1145,7 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
1112 dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch); 1145 dispatched += __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
1113 } 1146 }
1114 1147
1148 cfq_log(cfqd, "dispatched=%d", dispatched);
1115 return dispatched; 1149 return dispatched;
1116} 1150}
1117 1151
@@ -1130,6 +1164,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
1130 if (!atomic_dec_and_test(&cfqq->ref)) 1164 if (!atomic_dec_and_test(&cfqq->ref))
1131 return; 1165 return;
1132 1166
1167 cfq_log_cfqq(cfqd, cfqq, "put_queue");
1133 BUG_ON(rb_first(&cfqq->sort_list)); 1168 BUG_ON(rb_first(&cfqq->sort_list));
1134 BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); 1169 BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
1135 BUG_ON(cfq_cfqq_on_rr(cfqq)); 1170 BUG_ON(cfq_cfqq_on_rr(cfqq));
@@ -1177,8 +1212,19 @@ static void cfq_cic_free_rcu(struct rcu_head *head)
1177 kmem_cache_free(cfq_ioc_pool, cic); 1212 kmem_cache_free(cfq_ioc_pool, cic);
1178 elv_ioc_count_dec(ioc_count); 1213 elv_ioc_count_dec(ioc_count);
1179 1214
1180 if (ioc_gone && !elv_ioc_count_read(ioc_count)) 1215 if (ioc_gone) {
1181 complete(ioc_gone); 1216 /*
1217 * CFQ scheduler is exiting, grab exit lock and check
1218 * the pending io context count. If it hits zero,
1219 * complete ioc_gone and set it back to NULL
1220 */
1221 spin_lock(&ioc_gone_lock);
1222 if (ioc_gone && !elv_ioc_count_read(ioc_count)) {
1223 complete(ioc_gone);
1224 ioc_gone = NULL;
1225 }
1226 spin_unlock(&ioc_gone_lock);
1227 }
1182} 1228}
1183 1229
1184static void cfq_cic_free(struct cfq_io_context *cic) 1230static void cfq_cic_free(struct cfq_io_context *cic)
@@ -1427,6 +1473,8 @@ retry:
1427 cfq_mark_cfqq_idle_window(cfqq); 1473 cfq_mark_cfqq_idle_window(cfqq);
1428 cfq_mark_cfqq_sync(cfqq); 1474 cfq_mark_cfqq_sync(cfqq);
1429 } 1475 }
1476 cfqq->pid = current->pid;
1477 cfq_log_cfqq(cfqd, cfqq, "alloced");
1430 } 1478 }
1431 1479
1432 if (new_cfqq) 1480 if (new_cfqq)
@@ -1675,7 +1723,7 @@ static void
1675cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, 1723cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1676 struct cfq_io_context *cic) 1724 struct cfq_io_context *cic)
1677{ 1725{
1678 int enable_idle; 1726 int old_idle, enable_idle;
1679 1727
1680 /* 1728 /*
1681 * Don't idle for async or idle io prio class 1729 * Don't idle for async or idle io prio class
@@ -1683,7 +1731,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1683 if (!cfq_cfqq_sync(cfqq) || cfq_class_idle(cfqq)) 1731 if (!cfq_cfqq_sync(cfqq) || cfq_class_idle(cfqq))
1684 return; 1732 return;
1685 1733
1686 enable_idle = cfq_cfqq_idle_window(cfqq); 1734 enable_idle = old_idle = cfq_cfqq_idle_window(cfqq);
1687 1735
1688 if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle || 1736 if (!atomic_read(&cic->ioc->nr_tasks) || !cfqd->cfq_slice_idle ||
1689 (cfqd->hw_tag && CIC_SEEKY(cic))) 1737 (cfqd->hw_tag && CIC_SEEKY(cic)))
@@ -1695,10 +1743,13 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
1695 enable_idle = 1; 1743 enable_idle = 1;
1696 } 1744 }
1697 1745
1698 if (enable_idle) 1746 if (old_idle != enable_idle) {
1699 cfq_mark_cfqq_idle_window(cfqq); 1747 cfq_log_cfqq(cfqd, cfqq, "idle=%d", enable_idle);
1700 else 1748 if (enable_idle)
1701 cfq_clear_cfqq_idle_window(cfqq); 1749 cfq_mark_cfqq_idle_window(cfqq);
1750 else
1751 cfq_clear_cfqq_idle_window(cfqq);
1752 }
1702} 1753}
1703 1754
1704/* 1755/*
@@ -1757,6 +1808,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
1757 */ 1808 */
1758static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) 1809static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
1759{ 1810{
1811 cfq_log_cfqq(cfqd, cfqq, "preempt");
1760 cfq_slice_expired(cfqd, 1); 1812 cfq_slice_expired(cfqd, 1);
1761 1813
1762 /* 1814 /*
@@ -1818,6 +1870,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq)
1818 struct cfq_data *cfqd = q->elevator->elevator_data; 1870 struct cfq_data *cfqd = q->elevator->elevator_data;
1819 struct cfq_queue *cfqq = RQ_CFQQ(rq); 1871 struct cfq_queue *cfqq = RQ_CFQQ(rq);
1820 1872
1873 cfq_log_cfqq(cfqd, cfqq, "insert_request");
1821 cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc); 1874 cfq_init_prio_data(cfqq, RQ_CIC(rq)->ioc);
1822 1875
1823 cfq_add_rq_rb(rq); 1876 cfq_add_rq_rb(rq);
@@ -1835,6 +1888,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)
1835 unsigned long now; 1888 unsigned long now;
1836 1889
1837 now = jiffies; 1890 now = jiffies;
1891 cfq_log_cfqq(cfqd, cfqq, "complete");
1838 1892
1839 WARN_ON(!cfqd->rq_in_driver); 1893 WARN_ON(!cfqd->rq_in_driver);
1840 WARN_ON(!cfqq->dispatched); 1894 WARN_ON(!cfqq->dispatched);
@@ -2004,6 +2058,7 @@ queue_fail:
2004 2058
2005 cfq_schedule_dispatch(cfqd); 2059 cfq_schedule_dispatch(cfqd);
2006 spin_unlock_irqrestore(q->queue_lock, flags); 2060 spin_unlock_irqrestore(q->queue_lock, flags);
2061 cfq_log(cfqd, "set_request fail");
2007 return 1; 2062 return 1;
2008} 2063}
2009 2064
@@ -2029,6 +2084,8 @@ static void cfq_idle_slice_timer(unsigned long data)
2029 unsigned long flags; 2084 unsigned long flags;
2030 int timed_out = 1; 2085 int timed_out = 1;
2031 2086
2087 cfq_log(cfqd, "idle timer fired");
2088
2032 spin_lock_irqsave(cfqd->queue->queue_lock, flags); 2089 spin_lock_irqsave(cfqd->queue->queue_lock, flags);
2033 2090
2034 cfqq = cfqd->active_queue; 2091 cfqq = cfqd->active_queue;
@@ -2317,7 +2374,7 @@ static void __exit cfq_exit(void)
2317 * pending RCU callbacks 2374 * pending RCU callbacks
2318 */ 2375 */
2319 if (elv_ioc_count_read(ioc_count)) 2376 if (elv_ioc_count_read(ioc_count))
2320 wait_for_completion(ioc_gone); 2377 wait_for_completion(&all_gone);
2321 cfq_slab_kill(); 2378 cfq_slab_kill();
2322} 2379}
2323 2380