summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJun'ichi "Nick" Nomura <j-nomura@ce.jp.nec.com>2006-02-01 12:04:53 +0100
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-01 17:53:11 +0100
commit3eaf840e0b0046f56602c524c7ba58a82f5526c5 (patch)
treede525d358029dd1744aa2570fe8b8f8add5f8dd1
parent[PATCH] device-mapper statistics: basic (diff)
downloadlinux-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.c2
-rw-r--r--drivers/md/dm.c35
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);