diff options
author | Jun'ichi "Nick" Nomura <j-nomura@ce.jp.nec.com> | 2006-02-01 12:04:53 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-01 17:53:11 +0100 |
commit | 3eaf840e0b0046f56602c524c7ba58a82f5526c5 (patch) | |
tree | de525d358029dd1744aa2570fe8b8f8add5f8dd1 | |
parent | [PATCH] device-mapper statistics: basic (diff) | |
download | linux-3eaf840e0b0046f56602c524c7ba58a82f5526c5.tar.xz linux-3eaf840e0b0046f56602c524c7ba58a82f5526c5.zip |
[PATCH] device-mapper disk statistics: timing
Record I/O timing statistics
The start time is added to struct dm_io, an existing structure allocated
privately internally within dm and attached to each incoming bio.
We export disk_round_stats() from block/ll_rw_blk.c instead of creating a
private clone.
Signed-off-by: Jun'ichi "Nick" Nomura <j-nomura@ce.jp.nec.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | block/ll_rw_blk.c | 2 | ||||
-rw-r--r-- | drivers/md/dm.c | 35 |
2 files changed, 35 insertions, 2 deletions
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index d38b4afa37ef..f9fc07efd2da 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2579,6 +2579,8 @@ void disk_round_stats(struct gendisk *disk) disk->stamp = now; } +EXPORT_SYMBOL_GPL(disk_round_stats); + /* * queue lock must be held */ diff --git a/drivers/md/dm.c b/drivers/md/dm.c index c47518386c91..e9adeb9d172f 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -31,6 +31,7 @@ struct dm_io { int error; struct bio *bio; atomic_t io_count; + unsigned long start_time; }; /* @@ -244,6 +245,36 @@ static inline void free_tio(struct mapped_device *md, struct target_io *tio) mempool_free(tio, md->tio_pool); } +static void start_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + + io->start_time = jiffies; + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = atomic_inc_return(&md->pending); +} + +static int end_io_acct(struct dm_io *io) +{ + struct mapped_device *md = io->md; + struct bio *bio = io->bio; + unsigned long duration = jiffies - io->start_time; + int pending; + int rw = bio_data_dir(bio); + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + + disk_stat_add(dm_disk(md), ticks[rw], duration); + + return !pending; +} + /* * Add the bio to the list of deferred io. */ @@ -299,7 +330,7 @@ static void dec_pending(struct dm_io *io, int error) io->error = error; if (atomic_dec_and_test(&io->io_count)) { - if (atomic_dec_and_test(&io->md->pending)) + if (end_io_acct(io)) /* nudge anyone waiting on suspend queue */ wake_up(&io->md->wait); @@ -554,7 +585,7 @@ static void __split_bio(struct mapped_device *md, struct bio *bio) ci.sector_count = bio_sectors(bio); ci.idx = bio->bi_idx; - atomic_inc(&md->pending); + start_io_acct(ci.io); while (ci.sector_count) __clone_and_map(&ci); |