diff options
Diffstat (limited to 'drivers/md/dm.c')
-rw-r--r-- | drivers/md/dm.c | 39 |
1 files changed, 37 insertions, 2 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 8c16359f8b01..e9adeb9d172f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -31,6 +31,7 @@ struct dm_io { | |||
31 | int error; | 31 | int error; |
32 | struct bio *bio; | 32 | struct bio *bio; |
33 | atomic_t io_count; | 33 | atomic_t io_count; |
34 | unsigned long start_time; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | /* | 37 | /* |
@@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) | |||
244 | mempool_free(tio, md->tio_pool); | 245 | mempool_free(tio, md->tio_pool); |
245 | } | 246 | } |
246 | 247 | ||
248 | static void start_io_acct(struct dm_io *io) | ||
249 | { | ||
250 | struct mapped_device *md = io->md; | ||
251 | |||
252 | io->start_time = jiffies; | ||
253 | |||
254 | preempt_disable(); | ||
255 | disk_round_stats(dm_disk(md)); | ||
256 | preempt_enable(); | ||
257 | dm_disk(md)->in_flight = atomic_inc_return(&md->pending); | ||
258 | } | ||
259 | |||
260 | static int end_io_acct(struct dm_io *io) | ||
261 | { | ||
262 | struct mapped_device *md = io->md; | ||
263 | struct bio *bio = io->bio; | ||
264 | unsigned long duration = jiffies - io->start_time; | ||
265 | int pending; | ||
266 | int rw = bio_data_dir(bio); | ||
267 | |||
268 | preempt_disable(); | ||
269 | disk_round_stats(dm_disk(md)); | ||
270 | preempt_enable(); | ||
271 | dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); | ||
272 | |||
273 | disk_stat_add(dm_disk(md), ticks[rw], duration); | ||
274 | |||
275 | return !pending; | ||
276 | } | ||
277 | |||
247 | /* | 278 | /* |
248 | * Add the bio to the list of deferred io. | 279 | * Add the bio to the list of deferred io. |
249 | */ | 280 | */ |
@@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error) | |||
299 | io->error = error; | 330 | io->error = error; |
300 | 331 | ||
301 | if (atomic_dec_and_test(&io->io_count)) { | 332 | if (atomic_dec_and_test(&io->io_count)) { |
302 | if (atomic_dec_and_test(&io->md->pending)) | 333 | if (end_io_acct(io)) |
303 | /* nudge anyone waiting on suspend queue */ | 334 | /* nudge anyone waiting on suspend queue */ |
304 | wake_up(&io->md->wait); | 335 | wake_up(&io->md->wait); |
305 | 336 | ||
@@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
554 | ci.sector_count = bio_sectors(bio); | 585 | ci.sector_count = bio_sectors(bio); |
555 | ci.idx = bio->bi_idx; | 586 | ci.idx = bio->bi_idx; |
556 | 587 | ||
557 | atomic_inc(&md->pending); | 588 | start_io_acct(ci.io); |
558 | while (ci.sector_count) | 589 | while (ci.sector_count) |
559 | __clone_and_map(&ci); | 590 | __clone_and_map(&ci); |
560 | 591 | ||
@@ -573,10 +604,14 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) | |||
573 | static int dm_request(request_queue_t *q, struct bio *bio) | 604 | static int dm_request(request_queue_t *q, struct bio *bio) |
574 | { | 605 | { |
575 | int r; | 606 | int r; |
607 | int rw = bio_data_dir(bio); | ||
576 | struct mapped_device *md = q->queuedata; | 608 | struct mapped_device *md = q->queuedata; |
577 | 609 | ||
578 | down_read(&md->io_lock); | 610 | down_read(&md->io_lock); |
579 | 611 | ||
612 | disk_stat_inc(dm_disk(md), ios[rw]); | ||
613 | disk_stat_add(dm_disk(md), sectors[rw], bio_sectors(bio)); | ||
614 | |||
580 | /* | 615 | /* |
581 | * If we're suspended we have to queue | 616 | * If we're suspended we have to queue |
582 | * this io for later. | 617 | * this io for later. |