diff options
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r-- | block/cfq-iosched.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index dee9d9378fee..838834be115b 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk> | 7 | * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk> |
8 | */ | 8 | */ |
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/slab.h> | ||
10 | #include <linux/blkdev.h> | 11 | #include <linux/blkdev.h> |
11 | #include <linux/elevator.h> | 12 | #include <linux/elevator.h> |
12 | #include <linux/jiffies.h> | 13 | #include <linux/jiffies.h> |
@@ -47,6 +48,7 @@ static const int cfq_hist_divisor = 4; | |||
47 | #define CFQ_SERVICE_SHIFT 12 | 48 | #define CFQ_SERVICE_SHIFT 12 |
48 | 49 | ||
49 | #define CFQQ_SEEK_THR (sector_t)(8 * 100) | 50 | #define CFQQ_SEEK_THR (sector_t)(8 * 100) |
51 | #define CFQQ_CLOSE_THR (sector_t)(8 * 1024) | ||
50 | #define CFQQ_SECT_THR_NONROT (sector_t)(2 * 32) | 52 | #define CFQQ_SECT_THR_NONROT (sector_t)(2 * 32) |
51 | #define CFQQ_SEEKY(cfqq) (hweight32(cfqq->seek_history) > 32/8) | 53 | #define CFQQ_SEEKY(cfqq) (hweight32(cfqq->seek_history) > 32/8) |
52 | 54 | ||
@@ -947,6 +949,11 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create) | |||
947 | unsigned int major, minor; | 949 | unsigned int major, minor; |
948 | 950 | ||
949 | cfqg = cfqg_of_blkg(blkiocg_lookup_group(blkcg, key)); | 951 | cfqg = cfqg_of_blkg(blkiocg_lookup_group(blkcg, key)); |
952 | if (cfqg && !cfqg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { | ||
953 | sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); | ||
954 | cfqg->blkg.dev = MKDEV(major, minor); | ||
955 | goto done; | ||
956 | } | ||
950 | if (cfqg || !create) | 957 | if (cfqg || !create) |
951 | goto done; | 958 | goto done; |
952 | 959 | ||
@@ -1517,7 +1524,8 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd, | |||
1517 | struct cfq_queue *cfqq) | 1524 | struct cfq_queue *cfqq) |
1518 | { | 1525 | { |
1519 | if (cfqq) { | 1526 | if (cfqq) { |
1520 | cfq_log_cfqq(cfqd, cfqq, "set_active"); | 1527 | cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d", |
1528 | cfqd->serving_prio, cfqd->serving_type); | ||
1521 | cfqq->slice_start = 0; | 1529 | cfqq->slice_start = 0; |
1522 | cfqq->dispatch_start = jiffies; | 1530 | cfqq->dispatch_start = jiffies; |
1523 | cfqq->allocated_slice = 0; | 1531 | cfqq->allocated_slice = 0; |
@@ -1660,9 +1668,9 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd, | |||
1660 | } | 1668 | } |
1661 | 1669 | ||
1662 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq, | 1670 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq, |
1663 | struct request *rq, bool for_preempt) | 1671 | struct request *rq) |
1664 | { | 1672 | { |
1665 | return cfq_dist_from_last(cfqd, rq) <= CFQQ_SEEK_THR; | 1673 | return cfq_dist_from_last(cfqd, rq) <= CFQQ_CLOSE_THR; |
1666 | } | 1674 | } |
1667 | 1675 | ||
1668 | static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | 1676 | static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, |
@@ -1689,7 +1697,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | |||
1689 | * will contain the closest sector. | 1697 | * will contain the closest sector. |
1690 | */ | 1698 | */ |
1691 | __cfqq = rb_entry(parent, struct cfq_queue, p_node); | 1699 | __cfqq = rb_entry(parent, struct cfq_queue, p_node); |
1692 | if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false)) | 1700 | if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq)) |
1693 | return __cfqq; | 1701 | return __cfqq; |
1694 | 1702 | ||
1695 | if (blk_rq_pos(__cfqq->next_rq) < sector) | 1703 | if (blk_rq_pos(__cfqq->next_rq) < sector) |
@@ -1700,7 +1708,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | |||
1700 | return NULL; | 1708 | return NULL; |
1701 | 1709 | ||
1702 | __cfqq = rb_entry(node, struct cfq_queue, p_node); | 1710 | __cfqq = rb_entry(node, struct cfq_queue, p_node); |
1703 | if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false)) | 1711 | if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq)) |
1704 | return __cfqq; | 1712 | return __cfqq; |
1705 | 1713 | ||
1706 | return NULL; | 1714 | return NULL; |
@@ -1721,6 +1729,8 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, | |||
1721 | { | 1729 | { |
1722 | struct cfq_queue *cfqq; | 1730 | struct cfq_queue *cfqq; |
1723 | 1731 | ||
1732 | if (cfq_class_idle(cur_cfqq)) | ||
1733 | return NULL; | ||
1724 | if (!cfq_cfqq_sync(cur_cfqq)) | 1734 | if (!cfq_cfqq_sync(cur_cfqq)) |
1725 | return NULL; | 1735 | return NULL; |
1726 | if (CFQQ_SEEKY(cur_cfqq)) | 1736 | if (CFQQ_SEEKY(cur_cfqq)) |
@@ -1787,7 +1797,11 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
1787 | * Otherwise, we do only if they are the last ones | 1797 | * Otherwise, we do only if they are the last ones |
1788 | * in their service tree. | 1798 | * in their service tree. |
1789 | */ | 1799 | */ |
1790 | return service_tree->count == 1 && cfq_cfqq_sync(cfqq); | 1800 | if (service_tree->count == 1 && cfq_cfqq_sync(cfqq)) |
1801 | return 1; | ||
1802 | cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d", | ||
1803 | service_tree->count); | ||
1804 | return 0; | ||
1791 | } | 1805 | } |
1792 | 1806 | ||
1793 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) | 1807 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) |
@@ -1832,8 +1846,11 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) | |||
1832 | * time slice. | 1846 | * time slice. |
1833 | */ | 1847 | */ |
1834 | if (sample_valid(cic->ttime_samples) && | 1848 | if (sample_valid(cic->ttime_samples) && |
1835 | (cfqq->slice_end - jiffies < cic->ttime_mean)) | 1849 | (cfqq->slice_end - jiffies < cic->ttime_mean)) { |
1850 | cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%d", | ||
1851 | cic->ttime_mean); | ||
1836 | return; | 1852 | return; |
1853 | } | ||
1837 | 1854 | ||
1838 | cfq_mark_cfqq_wait_request(cfqq); | 1855 | cfq_mark_cfqq_wait_request(cfqq); |
1839 | 1856 | ||
@@ -2041,6 +2058,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg) | |||
2041 | slice = max(slice, 2 * cfqd->cfq_slice_idle); | 2058 | slice = max(slice, 2 * cfqd->cfq_slice_idle); |
2042 | 2059 | ||
2043 | slice = max_t(unsigned, slice, CFQ_MIN_TT); | 2060 | slice = max_t(unsigned, slice, CFQ_MIN_TT); |
2061 | cfq_log(cfqd, "workload slice:%d", slice); | ||
2044 | cfqd->workload_expires = jiffies + slice; | 2062 | cfqd->workload_expires = jiffies + slice; |
2045 | cfqd->noidle_tree_requires_idle = false; | 2063 | cfqd->noidle_tree_requires_idle = false; |
2046 | } | 2064 | } |
@@ -2188,10 +2206,13 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd) | |||
2188 | struct cfq_queue *cfqq; | 2206 | struct cfq_queue *cfqq; |
2189 | int dispatched = 0; | 2207 | int dispatched = 0; |
2190 | 2208 | ||
2191 | while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) | 2209 | /* Expire the timeslice of the current active queue first */ |
2210 | cfq_slice_expired(cfqd, 0); | ||
2211 | while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) { | ||
2212 | __cfq_set_active_queue(cfqd, cfqq); | ||
2192 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); | 2213 | dispatched += __cfq_forced_dispatch_cfqq(cfqq); |
2214 | } | ||
2193 | 2215 | ||
2194 | cfq_slice_expired(cfqd, 0); | ||
2195 | BUG_ON(cfqd->busy_queues); | 2216 | BUG_ON(cfqd->busy_queues); |
2196 | 2217 | ||
2197 | cfq_log(cfqd, "forced_dispatch=%d", dispatched); | 2218 | cfq_log(cfqd, "forced_dispatch=%d", dispatched); |
@@ -3103,7 +3124,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, | |||
3103 | * if this request is as-good as one we would expect from the | 3124 | * if this request is as-good as one we would expect from the |
3104 | * current cfqq, let it preempt | 3125 | * current cfqq, let it preempt |
3105 | */ | 3126 | */ |
3106 | if (cfq_rq_close(cfqd, cfqq, rq, true)) | 3127 | if (cfq_rq_close(cfqd, cfqq, rq)) |
3107 | return true; | 3128 | return true; |
3108 | 3129 | ||
3109 | return false; | 3130 | return false; |
@@ -3307,6 +3328,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) | |||
3307 | if (cfq_should_wait_busy(cfqd, cfqq)) { | 3328 | if (cfq_should_wait_busy(cfqd, cfqq)) { |
3308 | cfqq->slice_end = jiffies + cfqd->cfq_slice_idle; | 3329 | cfqq->slice_end = jiffies + cfqd->cfq_slice_idle; |
3309 | cfq_mark_cfqq_wait_busy(cfqq); | 3330 | cfq_mark_cfqq_wait_busy(cfqq); |
3331 | cfq_log_cfqq(cfqd, cfqq, "will busy wait"); | ||
3310 | } | 3332 | } |
3311 | 3333 | ||
3312 | /* | 3334 | /* |