diff options
Diffstat (limited to 'block/cfq-iosched.c')
| -rw-r--r-- | block/cfq-iosched.c | 44 | 
1 files changed, 34 insertions, 10 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index dee9d9378fe..5f127cfb2e9 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -7,6 +7,7 @@   *  Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>   */  #include <linux/module.h> +#include <linux/slab.h>  #include <linux/blkdev.h>  #include <linux/elevator.h>  #include <linux/jiffies.h> @@ -47,6 +48,7 @@ static const int cfq_hist_divisor = 4;  #define CFQ_SERVICE_SHIFT       12  #define CFQQ_SEEK_THR		(sector_t)(8 * 100) +#define CFQQ_CLOSE_THR		(sector_t)(8 * 1024)  #define CFQQ_SECT_THR_NONROT	(sector_t)(2 * 32)  #define CFQQ_SEEKY(cfqq)	(hweight32(cfqq->seek_history) > 32/8) @@ -947,6 +949,11 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)  	unsigned int major, minor;  	cfqg = cfqg_of_blkg(blkiocg_lookup_group(blkcg, key)); +	if (cfqg && !cfqg->blkg.dev && bdi->dev && dev_name(bdi->dev)) { +		sscanf(dev_name(bdi->dev), "%u:%u", &major, &minor); +		cfqg->blkg.dev = MKDEV(major, minor); +		goto done; +	}  	if (cfqg || !create)  		goto done; @@ -1517,7 +1524,8 @@ static void __cfq_set_active_queue(struct cfq_data *cfqd,  				   struct cfq_queue *cfqq)  {  	if (cfqq) { -		cfq_log_cfqq(cfqd, cfqq, "set_active"); +		cfq_log_cfqq(cfqd, cfqq, "set_active wl_prio:%d wl_type:%d", +				cfqd->serving_prio, cfqd->serving_type);  		cfqq->slice_start = 0;  		cfqq->dispatch_start = jiffies;  		cfqq->allocated_slice = 0; @@ -1660,9 +1668,9 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd,  }  static inline int cfq_rq_close(struct cfq_data *cfqd, struct cfq_queue *cfqq, -			       struct request *rq, bool for_preempt) +			       struct request *rq)  { -	return cfq_dist_from_last(cfqd, rq) <= CFQQ_SEEK_THR; +	return cfq_dist_from_last(cfqd, rq) <= CFQQ_CLOSE_THR;  }  static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, @@ -1689,7 +1697,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,  	 * will contain the closest sector.  	 */  	__cfqq = rb_entry(parent, struct cfq_queue, p_node); -	if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false)) +	if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))  		return __cfqq;  	if (blk_rq_pos(__cfqq->next_rq) < sector) @@ -1700,7 +1708,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd,  		return NULL;  	__cfqq = rb_entry(node, struct cfq_queue, p_node); -	if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq, false)) +	if (cfq_rq_close(cfqd, cur_cfqq, __cfqq->next_rq))  		return __cfqq;  	return NULL; @@ -1721,6 +1729,8 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd,  {  	struct cfq_queue *cfqq; +	if (cfq_class_idle(cur_cfqq)) +		return NULL;  	if (!cfq_cfqq_sync(cur_cfqq))  		return NULL;  	if (CFQQ_SEEKY(cur_cfqq)) @@ -1787,7 +1797,11 @@ static bool cfq_should_idle(struct cfq_data *cfqd, struct cfq_queue *cfqq)  	 * Otherwise, we do only if they are the last ones  	 * in their service tree.  	 */ -	return service_tree->count == 1 && cfq_cfqq_sync(cfqq); +	if (service_tree->count == 1 && cfq_cfqq_sync(cfqq)) +		return 1; +	cfq_log_cfqq(cfqd, cfqq, "Not idling. st->count:%d", +			service_tree->count); +	return 0;  }  static void cfq_arm_slice_timer(struct cfq_data *cfqd) @@ -1832,8 +1846,11 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)  	 * time slice.  	 */  	if (sample_valid(cic->ttime_samples) && -	    (cfqq->slice_end - jiffies < cic->ttime_mean)) +	    (cfqq->slice_end - jiffies < cic->ttime_mean)) { +		cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%d", +				cic->ttime_mean);  		return; +	}  	cfq_mark_cfqq_wait_request(cfqq); @@ -2041,6 +2058,7 @@ static void choose_service_tree(struct cfq_data *cfqd, struct cfq_group *cfqg)  		slice = max(slice, 2 * cfqd->cfq_slice_idle);  	slice = max_t(unsigned, slice, CFQ_MIN_TT); +	cfq_log(cfqd, "workload slice:%d", slice);  	cfqd->workload_expires = jiffies + slice;  	cfqd->noidle_tree_requires_idle = false;  } @@ -2188,10 +2206,13 @@ static int cfq_forced_dispatch(struct cfq_data *cfqd)  	struct cfq_queue *cfqq;  	int dispatched = 0; -	while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) +	/* Expire the timeslice of the current active queue first */ +	cfq_slice_expired(cfqd, 0); +	while ((cfqq = cfq_get_next_queue_forced(cfqd)) != NULL) { +		__cfq_set_active_queue(cfqd, cfqq);  		dispatched += __cfq_forced_dispatch_cfqq(cfqq); +	} -	cfq_slice_expired(cfqd, 0);  	BUG_ON(cfqd->busy_queues);  	cfq_log(cfqd, "forced_dispatch=%d", dispatched); @@ -3103,7 +3124,7 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,  	 * if this request is as-good as one we would expect from the  	 * current cfqq, let it preempt  	 */ -	if (cfq_rq_close(cfqd, cfqq, rq, true)) +	if (cfq_rq_close(cfqd, cfqq, rq))  		return true;  	return false; @@ -3307,6 +3328,7 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq)  		if (cfq_should_wait_busy(cfqd, cfqq)) {  			cfqq->slice_end = jiffies + cfqd->cfq_slice_idle;  			cfq_mark_cfqq_wait_busy(cfqq); +			cfq_log_cfqq(cfqd, cfqq, "will busy wait");  		}  		/* @@ -3672,8 +3694,10 @@ static void *cfq_init_queue(struct request_queue *q)  	 * to make sure that cfq_put_cfqg() does not try to kfree root group  	 */  	atomic_set(&cfqg->ref, 1); +	rcu_read_lock();  	blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd,  					0); +	rcu_read_unlock();  #endif  	/*  	 * Not strictly needed (since RB_ROOT just clears the node and we  |