diff options
author | Divyesh Shah <dpshah@google.com> | 2010-04-09 00:15:10 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-04-09 02:36:08 -0400 |
commit | cdc1184cf4a7bd99f5473a91244197accc49146b (patch) | |
tree | ecd572867bfa5a82fa4ed16d7303448c7ea7d24c /block/blk-cgroup.c | |
parent | 812d402648f4fc1ab1091b2172a46fc1b367c724 (diff) |
blkio: Add io_queued and avg_queue_size stats
These stats are useful for getting a feel for the queue depth of the cgroup,
i.e., how filled up its queues are at a given instant and over the existence of
the cgroup. This ability is useful when debugging problems in the wild as it
helps understand the application's IO pattern w/o having to read through the
userspace code (coz its tedious or just not available) or w/o the ability
to run blktrace (since you may not have root access and/or not want to disturb
performance).
Signed-off-by: Divyesh Shah<dpshah@google.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/blk-cgroup.c')
-rw-r--r-- | block/blk-cgroup.c | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index d23b538858ce..1e0c4970b35d 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -81,6 +81,71 @@ static void blkio_add_stat(uint64_t *stat, uint64_t add, bool direction, | |||
81 | stat[BLKIO_STAT_ASYNC] += add; | 81 | stat[BLKIO_STAT_ASYNC] += add; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* | ||
85 | * Decrements the appropriate stat variable if non-zero depending on the | ||
86 | * request type. Panics on value being zero. | ||
87 | * This should be called with the blkg->stats_lock held. | ||
88 | */ | ||
89 | static void blkio_check_and_dec_stat(uint64_t *stat, bool direction, bool sync) | ||
90 | { | ||
91 | if (direction) { | ||
92 | BUG_ON(stat[BLKIO_STAT_WRITE] == 0); | ||
93 | stat[BLKIO_STAT_WRITE]--; | ||
94 | } else { | ||
95 | BUG_ON(stat[BLKIO_STAT_READ] == 0); | ||
96 | stat[BLKIO_STAT_READ]--; | ||
97 | } | ||
98 | if (sync) { | ||
99 | BUG_ON(stat[BLKIO_STAT_SYNC] == 0); | ||
100 | stat[BLKIO_STAT_SYNC]--; | ||
101 | } else { | ||
102 | BUG_ON(stat[BLKIO_STAT_ASYNC] == 0); | ||
103 | stat[BLKIO_STAT_ASYNC]--; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | #ifdef CONFIG_DEBUG_BLK_CGROUP | ||
108 | void blkiocg_update_set_active_queue_stats(struct blkio_group *blkg) | ||
109 | { | ||
110 | unsigned long flags; | ||
111 | struct blkio_group_stats *stats; | ||
112 | |||
113 | spin_lock_irqsave(&blkg->stats_lock, flags); | ||
114 | stats = &blkg->stats; | ||
115 | stats->avg_queue_size_sum += | ||
116 | stats->stat_arr[BLKIO_STAT_QUEUED][BLKIO_STAT_READ] + | ||
117 | stats->stat_arr[BLKIO_STAT_QUEUED][BLKIO_STAT_WRITE]; | ||
118 | stats->avg_queue_size_samples++; | ||
119 | spin_unlock_irqrestore(&blkg->stats_lock, flags); | ||
120 | } | ||
121 | EXPORT_SYMBOL_GPL(blkiocg_update_set_active_queue_stats); | ||
122 | #endif | ||
123 | |||
124 | void blkiocg_update_request_add_stats(struct blkio_group *blkg, | ||
125 | struct blkio_group *curr_blkg, bool direction, | ||
126 | bool sync) | ||
127 | { | ||
128 | unsigned long flags; | ||
129 | |||
130 | spin_lock_irqsave(&blkg->stats_lock, flags); | ||
131 | blkio_add_stat(blkg->stats.stat_arr[BLKIO_STAT_QUEUED], 1, direction, | ||
132 | sync); | ||
133 | spin_unlock_irqrestore(&blkg->stats_lock, flags); | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(blkiocg_update_request_add_stats); | ||
136 | |||
137 | void blkiocg_update_request_remove_stats(struct blkio_group *blkg, | ||
138 | bool direction, bool sync) | ||
139 | { | ||
140 | unsigned long flags; | ||
141 | |||
142 | spin_lock_irqsave(&blkg->stats_lock, flags); | ||
143 | blkio_check_and_dec_stat(blkg->stats.stat_arr[BLKIO_STAT_QUEUED], | ||
144 | direction, sync); | ||
145 | spin_unlock_irqrestore(&blkg->stats_lock, flags); | ||
146 | } | ||
147 | EXPORT_SYMBOL_GPL(blkiocg_update_request_remove_stats); | ||
148 | |||
84 | void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time) | 149 | void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time) |
85 | { | 150 | { |
86 | unsigned long flags; | 151 | unsigned long flags; |
@@ -253,14 +318,18 @@ blkiocg_reset_stats(struct cgroup *cgroup, struct cftype *cftype, u64 val) | |||
253 | struct blkio_cgroup *blkcg; | 318 | struct blkio_cgroup *blkcg; |
254 | struct blkio_group *blkg; | 319 | struct blkio_group *blkg; |
255 | struct hlist_node *n; | 320 | struct hlist_node *n; |
256 | struct blkio_group_stats *stats; | 321 | uint64_t queued[BLKIO_STAT_TOTAL]; |
322 | int i; | ||
257 | 323 | ||
258 | blkcg = cgroup_to_blkio_cgroup(cgroup); | 324 | blkcg = cgroup_to_blkio_cgroup(cgroup); |
259 | spin_lock_irq(&blkcg->lock); | 325 | spin_lock_irq(&blkcg->lock); |
260 | hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) { | 326 | hlist_for_each_entry(blkg, n, &blkcg->blkg_list, blkcg_node) { |
261 | spin_lock(&blkg->stats_lock); | 327 | spin_lock(&blkg->stats_lock); |
262 | stats = &blkg->stats; | 328 | for (i = 0; i < BLKIO_STAT_TOTAL; i++) |
263 | memset(stats, 0, sizeof(struct blkio_group_stats)); | 329 | queued[i] = blkg->stats.stat_arr[BLKIO_STAT_QUEUED][i]; |
330 | memset(&blkg->stats, 0, sizeof(struct blkio_group_stats)); | ||
331 | for (i = 0; i < BLKIO_STAT_TOTAL; i++) | ||
332 | blkg->stats.stat_arr[BLKIO_STAT_QUEUED][i] = queued[i]; | ||
264 | spin_unlock(&blkg->stats_lock); | 333 | spin_unlock(&blkg->stats_lock); |
265 | } | 334 | } |
266 | spin_unlock_irq(&blkcg->lock); | 335 | spin_unlock_irq(&blkcg->lock); |
@@ -323,6 +392,15 @@ static uint64_t blkio_get_stat(struct blkio_group *blkg, | |||
323 | return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, | 392 | return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, |
324 | blkg->stats.sectors, cb, dev); | 393 | blkg->stats.sectors, cb, dev); |
325 | #ifdef CONFIG_DEBUG_BLK_CGROUP | 394 | #ifdef CONFIG_DEBUG_BLK_CGROUP |
395 | if (type == BLKIO_STAT_AVG_QUEUE_SIZE) { | ||
396 | uint64_t sum = blkg->stats.avg_queue_size_sum; | ||
397 | uint64_t samples = blkg->stats.avg_queue_size_samples; | ||
398 | if (samples) | ||
399 | do_div(sum, samples); | ||
400 | else | ||
401 | sum = 0; | ||
402 | return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, sum, cb, dev); | ||
403 | } | ||
326 | if (type == BLKIO_STAT_DEQUEUE) | 404 | if (type == BLKIO_STAT_DEQUEUE) |
327 | return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, | 405 | return blkio_fill_stat(key_str, MAX_KEY_LEN - 1, |
328 | blkg->stats.dequeue, cb, dev); | 406 | blkg->stats.dequeue, cb, dev); |
@@ -376,8 +454,10 @@ SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1); | |||
376 | SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1); | 454 | SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1); |
377 | SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1); | 455 | SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1); |
378 | SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1); | 456 | SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1); |
457 | SHOW_FUNCTION_PER_GROUP(io_queued, BLKIO_STAT_QUEUED, 1); | ||
379 | #ifdef CONFIG_DEBUG_BLK_CGROUP | 458 | #ifdef CONFIG_DEBUG_BLK_CGROUP |
380 | SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0); | 459 | SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0); |
460 | SHOW_FUNCTION_PER_GROUP(avg_queue_size, BLKIO_STAT_AVG_QUEUE_SIZE, 0); | ||
381 | #endif | 461 | #endif |
382 | #undef SHOW_FUNCTION_PER_GROUP | 462 | #undef SHOW_FUNCTION_PER_GROUP |
383 | 463 | ||
@@ -425,14 +505,22 @@ struct cftype blkio_files[] = { | |||
425 | .read_map = blkiocg_io_merged_read, | 505 | .read_map = blkiocg_io_merged_read, |
426 | }, | 506 | }, |
427 | { | 507 | { |
508 | .name = "io_queued", | ||
509 | .read_map = blkiocg_io_queued_read, | ||
510 | }, | ||
511 | { | ||
428 | .name = "reset_stats", | 512 | .name = "reset_stats", |
429 | .write_u64 = blkiocg_reset_stats, | 513 | .write_u64 = blkiocg_reset_stats, |
430 | }, | 514 | }, |
431 | #ifdef CONFIG_DEBUG_BLK_CGROUP | 515 | #ifdef CONFIG_DEBUG_BLK_CGROUP |
432 | { | 516 | { |
517 | .name = "avg_queue_size", | ||
518 | .read_map = blkiocg_avg_queue_size_read, | ||
519 | }, | ||
520 | { | ||
433 | .name = "dequeue", | 521 | .name = "dequeue", |
434 | .read_map = blkiocg_dequeue_read, | 522 | .read_map = blkiocg_dequeue_read, |
435 | }, | 523 | }, |
436 | #endif | 524 | #endif |
437 | }; | 525 | }; |
438 | 526 | ||