1
0
Fork 0

blk-cgroup: Add unaccounted time to timeslice_used.

There are two kind of times that tasks are not charged for: the first
seek and the extra time slice used over the allocated timeslice. Both
of these exported as a new unaccounted_time stat.

I think it would be good to have this reported in 'time' as well, but
that is probably a separate discussion.

Signed-off-by: Justin TerAvest <teravest@google.com>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
hifive-unleashed-5.1
Justin TerAvest 2011-03-12 16:54:00 +01:00 committed by Jens Axboe
parent 1f940bdfc0
commit 167400d340
4 changed files with 41 additions and 14 deletions

View File

@ -371,12 +371,14 @@ void blkiocg_update_io_remove_stats(struct blkio_group *blkg,
} }
EXPORT_SYMBOL_GPL(blkiocg_update_io_remove_stats); EXPORT_SYMBOL_GPL(blkiocg_update_io_remove_stats);
void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time) void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time,
unsigned long unaccounted_time)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&blkg->stats_lock, flags); spin_lock_irqsave(&blkg->stats_lock, flags);
blkg->stats.time += time; blkg->stats.time += time;
blkg->stats.unaccounted_time += unaccounted_time;
spin_unlock_irqrestore(&blkg->stats_lock, flags); spin_unlock_irqrestore(&blkg->stats_lock, flags);
} }
EXPORT_SYMBOL_GPL(blkiocg_update_timeslice_used); EXPORT_SYMBOL_GPL(blkiocg_update_timeslice_used);
@ -603,6 +605,9 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg,
if (type == BLKIO_STAT_SECTORS) if (type == BLKIO_STAT_SECTORS)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.sectors, cb, dev); blkg->stats.sectors, cb, dev);
if (type == BLKIO_STAT_UNACCOUNTED_TIME)
return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
blkg->stats.unaccounted_time, cb, dev);
#ifdef CONFIG_DEBUG_BLK_CGROUP #ifdef CONFIG_DEBUG_BLK_CGROUP
if (type == BLKIO_STAT_AVG_QUEUE_SIZE) { if (type == BLKIO_STAT_AVG_QUEUE_SIZE) {
uint64_t sum = blkg->stats.avg_queue_size_sum; uint64_t sum = blkg->stats.avg_queue_size_sum;
@ -1106,6 +1111,9 @@ static int blkiocg_file_read_map(struct cgroup *cgrp, struct cftype *cft,
case BLKIO_PROP_sectors: case BLKIO_PROP_sectors:
return blkio_read_blkg_stats(blkcg, cft, cb, return blkio_read_blkg_stats(blkcg, cft, cb,
BLKIO_STAT_SECTORS, 0); BLKIO_STAT_SECTORS, 0);
case BLKIO_PROP_unaccounted_time:
return blkio_read_blkg_stats(blkcg, cft, cb,
BLKIO_STAT_UNACCOUNTED_TIME, 0);
case BLKIO_PROP_io_service_bytes: case BLKIO_PROP_io_service_bytes:
return blkio_read_blkg_stats(blkcg, cft, cb, return blkio_read_blkg_stats(blkcg, cft, cb,
BLKIO_STAT_SERVICE_BYTES, 1); BLKIO_STAT_SERVICE_BYTES, 1);
@ -1261,6 +1269,12 @@ struct cftype blkio_files[] = {
BLKIO_PROP_sectors), BLKIO_PROP_sectors),
.read_map = blkiocg_file_read_map, .read_map = blkiocg_file_read_map,
}, },
{
.name = "unaccounted_time",
.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
BLKIO_PROP_unaccounted_time),
.read_map = blkiocg_file_read_map,
},
{ {
.name = "io_service_bytes", .name = "io_service_bytes",
.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP, .private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,

View File

@ -49,6 +49,8 @@ enum stat_type {
/* All the single valued stats go below this */ /* All the single valued stats go below this */
BLKIO_STAT_TIME, BLKIO_STAT_TIME,
BLKIO_STAT_SECTORS, BLKIO_STAT_SECTORS,
/* Time not charged to this cgroup */
BLKIO_STAT_UNACCOUNTED_TIME,
#ifdef CONFIG_DEBUG_BLK_CGROUP #ifdef CONFIG_DEBUG_BLK_CGROUP
BLKIO_STAT_AVG_QUEUE_SIZE, BLKIO_STAT_AVG_QUEUE_SIZE,
BLKIO_STAT_IDLE_TIME, BLKIO_STAT_IDLE_TIME,
@ -81,6 +83,7 @@ enum blkcg_file_name_prop {
BLKIO_PROP_io_serviced, BLKIO_PROP_io_serviced,
BLKIO_PROP_time, BLKIO_PROP_time,
BLKIO_PROP_sectors, BLKIO_PROP_sectors,
BLKIO_PROP_unaccounted_time,
BLKIO_PROP_io_service_time, BLKIO_PROP_io_service_time,
BLKIO_PROP_io_wait_time, BLKIO_PROP_io_wait_time,
BLKIO_PROP_io_merged, BLKIO_PROP_io_merged,
@ -114,6 +117,8 @@ struct blkio_group_stats {
/* total disk time and nr sectors dispatched by this group */ /* total disk time and nr sectors dispatched by this group */
uint64_t time; uint64_t time;
uint64_t sectors; uint64_t sectors;
/* Time not charged to this cgroup */
uint64_t unaccounted_time;
uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL]; uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL];
#ifdef CONFIG_DEBUG_BLK_CGROUP #ifdef CONFIG_DEBUG_BLK_CGROUP
/* Sum of number of IOs queued across all samples */ /* Sum of number of IOs queued across all samples */
@ -293,7 +298,8 @@ extern int blkiocg_del_blkio_group(struct blkio_group *blkg);
extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg, extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
void *key); void *key);
void blkiocg_update_timeslice_used(struct blkio_group *blkg, void blkiocg_update_timeslice_used(struct blkio_group *blkg,
unsigned long time); unsigned long time,
unsigned long unaccounted_time);
void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes,
bool direction, bool sync); bool direction, bool sync);
void blkiocg_update_completion_stats(struct blkio_group *blkg, void blkiocg_update_completion_stats(struct blkio_group *blkg,
@ -319,7 +325,9 @@ blkiocg_del_blkio_group(struct blkio_group *blkg) { return 0; }
static inline struct blkio_group * static inline struct blkio_group *
blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; } blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; }
static inline void blkiocg_update_timeslice_used(struct blkio_group *blkg, static inline void blkiocg_update_timeslice_used(struct blkio_group *blkg,
unsigned long time) {} unsigned long time,
unsigned long unaccounted_time)
{}
static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg, static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg,
uint64_t bytes, bool direction, bool sync) {} uint64_t bytes, bool direction, bool sync) {}
static inline void blkiocg_update_completion_stats(struct blkio_group *blkg, static inline void blkiocg_update_completion_stats(struct blkio_group *blkg,

View File

@ -899,7 +899,8 @@ cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1); cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
} }
static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq) static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq,
unsigned int *unaccounted_time)
{ {
unsigned int slice_used; unsigned int slice_used;
@ -918,8 +919,13 @@ static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
1); 1);
} else { } else {
slice_used = jiffies - cfqq->slice_start; slice_used = jiffies - cfqq->slice_start;
if (slice_used > cfqq->allocated_slice) if (slice_used > cfqq->allocated_slice) {
*unaccounted_time = slice_used - cfqq->allocated_slice;
slice_used = cfqq->allocated_slice; slice_used = cfqq->allocated_slice;
}
if (time_after(cfqq->slice_start, cfqq->dispatch_start))
*unaccounted_time += cfqq->slice_start -
cfqq->dispatch_start;
} }
return slice_used; return slice_used;
@ -929,12 +935,12 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
struct cfq_queue *cfqq) struct cfq_queue *cfqq)
{ {
struct cfq_rb_root *st = &cfqd->grp_service_tree; struct cfq_rb_root *st = &cfqd->grp_service_tree;
unsigned int used_sl, charge; unsigned int used_sl, charge, unaccounted_sl = 0;
int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg) int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg)
- cfqg->service_tree_idle.count; - cfqg->service_tree_idle.count;
BUG_ON(nr_sync < 0); BUG_ON(nr_sync < 0);
used_sl = charge = cfq_cfqq_slice_usage(cfqq); used_sl = charge = cfq_cfqq_slice_usage(cfqq, &unaccounted_sl);
if (iops_mode(cfqd)) if (iops_mode(cfqd))
charge = cfqq->slice_dispatch; charge = cfqq->slice_dispatch;
@ -960,7 +966,8 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u" cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u"
" sect=%u", used_sl, cfqq->slice_dispatch, charge, " sect=%u", used_sl, cfqq->slice_dispatch, charge,
iops_mode(cfqd), cfqq->nr_sectors); iops_mode(cfqd), cfqq->nr_sectors);
cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl); cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl,
unaccounted_sl);
cfq_blkiocg_set_start_empty_time(&cfqg->blkg); cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
} }
@ -3296,9 +3303,7 @@ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
BUG_ON(!cfq_cfqq_on_rr(cfqq)); BUG_ON(!cfq_cfqq_on_rr(cfqq));
cfq_service_tree_add(cfqd, cfqq, 1); cfq_service_tree_add(cfqd, cfqq, 1);
__cfq_set_active_queue(cfqd, cfqq);
cfqq->slice_end = 0;
cfq_mark_cfqq_slice_new(cfqq);
} }
/* /*

View File

@ -16,9 +16,9 @@ static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
} }
static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
unsigned long time) unsigned long time, unsigned long unaccounted_time)
{ {
blkiocg_update_timeslice_used(blkg, time); blkiocg_update_timeslice_used(blkg, time, unaccounted_time);
} }
static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg)
@ -85,7 +85,7 @@ static inline void cfq_blkiocg_update_dequeue_stats(struct blkio_group *blkg,
unsigned long dequeue) {} unsigned long dequeue) {}
static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg, static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
unsigned long time) {} unsigned long time, unsigned long unaccounted_time) {}
static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {} static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg, static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
bool direction, bool sync) {} bool direction, bool sync) {}