diff options
-rw-r--r-- | Documentation/cgroups/blkio-controller.txt | 5 | ||||
-rw-r--r-- | block/blk-cgroup.c | 17 | ||||
-rw-r--r-- | block/blk-cgroup.h | 8 | ||||
-rw-r--r-- | block/blk-core.c | 2 | ||||
-rw-r--r-- | block/cfq-iosched.c | 11 | ||||
-rw-r--r-- | block/elevator.c | 9 | ||||
-rw-r--r-- | include/linux/elevator.h | 6 |
7 files changed, 57 insertions, 1 deletions
diff --git a/Documentation/cgroups/blkio-controller.txt b/Documentation/cgroups/blkio-controller.txt index ed04fe9cce1a..810e30171a54 100644 --- a/Documentation/cgroups/blkio-controller.txt +++ b/Documentation/cgroups/blkio-controller.txt | |||
@@ -134,6 +134,11 @@ Details of cgroup files | |||
134 | minor number of the device, third field specifies the operation type | 134 | minor number of the device, third field specifies the operation type |
135 | and the fourth field specifies the io_wait_time in ns. | 135 | and the fourth field specifies the io_wait_time in ns. |
136 | 136 | ||
137 | - blkio.io_merged | ||
138 | - Total number of bios/requests merged into requests belonging to this | ||
139 | cgroup. This is further divided by the type of operation - read or | ||
140 | write, sync or async. | ||
141 | |||
137 | - blkio.dequeue | 142 | - blkio.dequeue |
138 | - Debugging aid only enabled if CONFIG_DEBUG_CFQ_IOSCHED=y. This | 143 | - Debugging aid only enabled if CONFIG_DEBUG_CFQ_IOSCHED=y. This |
139 | gives the statistics about how many a times a group was dequeued | 144 | gives the statistics about how many a times a group was dequeued |
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 6797df508821..d23b538858ce 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
@@ -127,6 +127,18 @@ void blkiocg_update_completion_stats(struct blkio_group *blkg, | |||
127 | } | 127 | } |
128 | EXPORT_SYMBOL_GPL(blkiocg_update_completion_stats); | 128 | EXPORT_SYMBOL_GPL(blkiocg_update_completion_stats); |
129 | 129 | ||
130 | void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction, | ||
131 | bool sync) | ||
132 | { | ||
133 | unsigned long flags; | ||
134 | |||
135 | spin_lock_irqsave(&blkg->stats_lock, flags); | ||
136 | blkio_add_stat(blkg->stats.stat_arr[BLKIO_STAT_MERGED], 1, direction, | ||
137 | sync); | ||
138 | spin_unlock_irqrestore(&blkg->stats_lock, flags); | ||
139 | } | ||
140 | EXPORT_SYMBOL_GPL(blkiocg_update_io_merged_stats); | ||
141 | |||
130 | void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, | 142 | void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg, |
131 | struct blkio_group *blkg, void *key, dev_t dev) | 143 | struct blkio_group *blkg, void *key, dev_t dev) |
132 | { | 144 | { |
@@ -363,6 +375,7 @@ SHOW_FUNCTION_PER_GROUP(io_service_bytes, BLKIO_STAT_SERVICE_BYTES, 1); | |||
363 | SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1); | 375 | SHOW_FUNCTION_PER_GROUP(io_serviced, BLKIO_STAT_SERVICED, 1); |
364 | SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1); | 376 | SHOW_FUNCTION_PER_GROUP(io_service_time, BLKIO_STAT_SERVICE_TIME, 1); |
365 | SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1); | 377 | SHOW_FUNCTION_PER_GROUP(io_wait_time, BLKIO_STAT_WAIT_TIME, 1); |
378 | SHOW_FUNCTION_PER_GROUP(io_merged, BLKIO_STAT_MERGED, 1); | ||
366 | #ifdef CONFIG_DEBUG_BLK_CGROUP | 379 | #ifdef CONFIG_DEBUG_BLK_CGROUP |
367 | SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0); | 380 | SHOW_FUNCTION_PER_GROUP(dequeue, BLKIO_STAT_DEQUEUE, 0); |
368 | #endif | 381 | #endif |
@@ -408,6 +421,10 @@ struct cftype blkio_files[] = { | |||
408 | .read_map = blkiocg_io_wait_time_read, | 421 | .read_map = blkiocg_io_wait_time_read, |
409 | }, | 422 | }, |
410 | { | 423 | { |
424 | .name = "io_merged", | ||
425 | .read_map = blkiocg_io_merged_read, | ||
426 | }, | ||
427 | { | ||
411 | .name = "reset_stats", | 428 | .name = "reset_stats", |
412 | .write_u64 = blkiocg_reset_stats, | 429 | .write_u64 = blkiocg_reset_stats, |
413 | }, | 430 | }, |
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index b22e55390a4f..470a29db6bec 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h | |||
@@ -34,6 +34,8 @@ enum stat_type { | |||
34 | BLKIO_STAT_SERVICED, | 34 | BLKIO_STAT_SERVICED, |
35 | /* Total time spent waiting in scheduler queue in ns */ | 35 | /* Total time spent waiting in scheduler queue in ns */ |
36 | BLKIO_STAT_WAIT_TIME, | 36 | BLKIO_STAT_WAIT_TIME, |
37 | /* Number of IOs merged */ | ||
38 | BLKIO_STAT_MERGED, | ||
37 | /* All the single valued stats go below this */ | 39 | /* All the single valued stats go below this */ |
38 | BLKIO_STAT_TIME, | 40 | BLKIO_STAT_TIME, |
39 | BLKIO_STAT_SECTORS, | 41 | BLKIO_STAT_SECTORS, |
@@ -61,7 +63,7 @@ struct blkio_group_stats { | |||
61 | /* total disk time and nr sectors dispatched by this group */ | 63 | /* total disk time and nr sectors dispatched by this group */ |
62 | uint64_t time; | 64 | uint64_t time; |
63 | uint64_t sectors; | 65 | uint64_t sectors; |
64 | uint64_t stat_arr[BLKIO_STAT_WAIT_TIME + 1][BLKIO_STAT_TOTAL]; | 66 | uint64_t stat_arr[BLKIO_STAT_MERGED + 1][BLKIO_STAT_TOTAL]; |
65 | #ifdef CONFIG_DEBUG_BLK_CGROUP | 67 | #ifdef CONFIG_DEBUG_BLK_CGROUP |
66 | /* How many times this group has been removed from service tree */ | 68 | /* How many times this group has been removed from service tree */ |
67 | unsigned long dequeue; | 69 | unsigned long dequeue; |
@@ -148,6 +150,8 @@ void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes, | |||
148 | bool direction, bool sync); | 150 | bool direction, bool sync); |
149 | void blkiocg_update_completion_stats(struct blkio_group *blkg, | 151 | void blkiocg_update_completion_stats(struct blkio_group *blkg, |
150 | uint64_t start_time, uint64_t io_start_time, bool direction, bool sync); | 152 | uint64_t start_time, uint64_t io_start_time, bool direction, bool sync); |
153 | void blkiocg_update_io_merged_stats(struct blkio_group *blkg, bool direction, | ||
154 | bool sync); | ||
151 | #else | 155 | #else |
152 | struct cgroup; | 156 | struct cgroup; |
153 | static inline struct blkio_cgroup * | 157 | static inline struct blkio_cgroup * |
@@ -169,5 +173,7 @@ static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg, | |||
169 | static inline void blkiocg_update_completion_stats(struct blkio_group *blkg, | 173 | static inline void blkiocg_update_completion_stats(struct blkio_group *blkg, |
170 | uint64_t start_time, uint64_t io_start_time, bool direction, | 174 | uint64_t start_time, uint64_t io_start_time, bool direction, |
171 | bool sync) {} | 175 | bool sync) {} |
176 | static inline void blkiocg_update_io_merged_stats(struct blkio_group *blkg, | ||
177 | bool direction, bool sync) {} | ||
172 | #endif | 178 | #endif |
173 | #endif /* _BLK_CGROUP_H */ | 179 | #endif /* _BLK_CGROUP_H */ |
diff --git a/block/blk-core.c b/block/blk-core.c index 4b1b29ef2cb0..e9a5ae25db8c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -1202,6 +1202,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) | |||
1202 | if (!blk_rq_cpu_valid(req)) | 1202 | if (!blk_rq_cpu_valid(req)) |
1203 | req->cpu = bio->bi_comp_cpu; | 1203 | req->cpu = bio->bi_comp_cpu; |
1204 | drive_stat_acct(req, 0); | 1204 | drive_stat_acct(req, 0); |
1205 | elv_bio_merged(q, req, bio); | ||
1205 | if (!attempt_back_merge(q, req)) | 1206 | if (!attempt_back_merge(q, req)) |
1206 | elv_merged_request(q, req, el_ret); | 1207 | elv_merged_request(q, req, el_ret); |
1207 | goto out; | 1208 | goto out; |
@@ -1235,6 +1236,7 @@ static int __make_request(struct request_queue *q, struct bio *bio) | |||
1235 | if (!blk_rq_cpu_valid(req)) | 1236 | if (!blk_rq_cpu_valid(req)) |
1236 | req->cpu = bio->bi_comp_cpu; | 1237 | req->cpu = bio->bi_comp_cpu; |
1237 | drive_stat_acct(req, 0); | 1238 | drive_stat_acct(req, 0); |
1239 | elv_bio_merged(q, req, bio); | ||
1238 | if (!attempt_front_merge(q, req)) | 1240 | if (!attempt_front_merge(q, req)) |
1239 | elv_merged_request(q, req, el_ret); | 1241 | elv_merged_request(q, req, el_ret); |
1240 | goto out; | 1242 | goto out; |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 5617ae030b15..4eb1906cf6c6 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -1467,6 +1467,14 @@ static void cfq_merged_request(struct request_queue *q, struct request *req, | |||
1467 | } | 1467 | } |
1468 | } | 1468 | } |
1469 | 1469 | ||
1470 | static void cfq_bio_merged(struct request_queue *q, struct request *req, | ||
1471 | struct bio *bio) | ||
1472 | { | ||
1473 | struct cfq_queue *cfqq = RQ_CFQQ(req); | ||
1474 | blkiocg_update_io_merged_stats(&cfqq->cfqg->blkg, bio_data_dir(bio), | ||
1475 | cfq_bio_sync(bio)); | ||
1476 | } | ||
1477 | |||
1470 | static void | 1478 | static void |
1471 | cfq_merged_requests(struct request_queue *q, struct request *rq, | 1479 | cfq_merged_requests(struct request_queue *q, struct request *rq, |
1472 | struct request *next) | 1480 | struct request *next) |
@@ -1484,6 +1492,8 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, | |||
1484 | if (cfqq->next_rq == next) | 1492 | if (cfqq->next_rq == next) |
1485 | cfqq->next_rq = rq; | 1493 | cfqq->next_rq = rq; |
1486 | cfq_remove_request(next); | 1494 | cfq_remove_request(next); |
1495 | blkiocg_update_io_merged_stats(&cfqq->cfqg->blkg, rq_data_dir(next), | ||
1496 | rq_is_sync(next)); | ||
1487 | } | 1497 | } |
1488 | 1498 | ||
1489 | static int cfq_allow_merge(struct request_queue *q, struct request *rq, | 1499 | static int cfq_allow_merge(struct request_queue *q, struct request *rq, |
@@ -3861,6 +3871,7 @@ static struct elevator_type iosched_cfq = { | |||
3861 | .elevator_merged_fn = cfq_merged_request, | 3871 | .elevator_merged_fn = cfq_merged_request, |
3862 | .elevator_merge_req_fn = cfq_merged_requests, | 3872 | .elevator_merge_req_fn = cfq_merged_requests, |
3863 | .elevator_allow_merge_fn = cfq_allow_merge, | 3873 | .elevator_allow_merge_fn = cfq_allow_merge, |
3874 | .elevator_bio_merged_fn = cfq_bio_merged, | ||
3864 | .elevator_dispatch_fn = cfq_dispatch_requests, | 3875 | .elevator_dispatch_fn = cfq_dispatch_requests, |
3865 | .elevator_add_req_fn = cfq_insert_request, | 3876 | .elevator_add_req_fn = cfq_insert_request, |
3866 | .elevator_activate_req_fn = cfq_activate_request, | 3877 | .elevator_activate_req_fn = cfq_activate_request, |
diff --git a/block/elevator.c b/block/elevator.c index 76e3702d5381..5e734592bb40 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
@@ -539,6 +539,15 @@ void elv_merge_requests(struct request_queue *q, struct request *rq, | |||
539 | q->last_merge = rq; | 539 | q->last_merge = rq; |
540 | } | 540 | } |
541 | 541 | ||
542 | void elv_bio_merged(struct request_queue *q, struct request *rq, | ||
543 | struct bio *bio) | ||
544 | { | ||
545 | struct elevator_queue *e = q->elevator; | ||
546 | |||
547 | if (e->ops->elevator_bio_merged_fn) | ||
548 | e->ops->elevator_bio_merged_fn(q, rq, bio); | ||
549 | } | ||
550 | |||
542 | void elv_requeue_request(struct request_queue *q, struct request *rq) | 551 | void elv_requeue_request(struct request_queue *q, struct request *rq) |
543 | { | 552 | { |
544 | /* | 553 | /* |
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 1cb3372e65d8..2c958f4fce1e 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
@@ -14,6 +14,9 @@ typedef void (elevator_merged_fn) (struct request_queue *, struct request *, int | |||
14 | 14 | ||
15 | typedef int (elevator_allow_merge_fn) (struct request_queue *, struct request *, struct bio *); | 15 | typedef int (elevator_allow_merge_fn) (struct request_queue *, struct request *, struct bio *); |
16 | 16 | ||
17 | typedef void (elevator_bio_merged_fn) (struct request_queue *, | ||
18 | struct request *, struct bio *); | ||
19 | |||
17 | typedef int (elevator_dispatch_fn) (struct request_queue *, int); | 20 | typedef int (elevator_dispatch_fn) (struct request_queue *, int); |
18 | 21 | ||
19 | typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); | 22 | typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); |
@@ -36,6 +39,7 @@ struct elevator_ops | |||
36 | elevator_merged_fn *elevator_merged_fn; | 39 | elevator_merged_fn *elevator_merged_fn; |
37 | elevator_merge_req_fn *elevator_merge_req_fn; | 40 | elevator_merge_req_fn *elevator_merge_req_fn; |
38 | elevator_allow_merge_fn *elevator_allow_merge_fn; | 41 | elevator_allow_merge_fn *elevator_allow_merge_fn; |
42 | elevator_bio_merged_fn *elevator_bio_merged_fn; | ||
39 | 43 | ||
40 | elevator_dispatch_fn *elevator_dispatch_fn; | 44 | elevator_dispatch_fn *elevator_dispatch_fn; |
41 | elevator_add_req_fn *elevator_add_req_fn; | 45 | elevator_add_req_fn *elevator_add_req_fn; |
@@ -103,6 +107,8 @@ extern int elv_merge(struct request_queue *, struct request **, struct bio *); | |||
103 | extern void elv_merge_requests(struct request_queue *, struct request *, | 107 | extern void elv_merge_requests(struct request_queue *, struct request *, |
104 | struct request *); | 108 | struct request *); |
105 | extern void elv_merged_request(struct request_queue *, struct request *, int); | 109 | extern void elv_merged_request(struct request_queue *, struct request *, int); |
110 | extern void elv_bio_merged(struct request_queue *q, struct request *, | ||
111 | struct bio *); | ||
106 | extern void elv_requeue_request(struct request_queue *, struct request *); | 112 | extern void elv_requeue_request(struct request_queue *, struct request *); |
107 | extern int elv_queue_empty(struct request_queue *); | 113 | extern int elv_queue_empty(struct request_queue *); |
108 | extern struct request *elv_former_request(struct request_queue *, struct request *); | 114 | extern struct request *elv_former_request(struct request_queue *, struct request *); |