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. From: "Jun'ichi \"Nick\" Nomura" Index: current-quilt-publish/drivers/md/dm.c =================================================================== --- current-quilt-publish.orig/drivers/md/dm.c 2006-01-03 21:08:09.000000000 +0000 +++ current-quilt-publish/drivers/md/dm.c 2006-01-03 21:08:23.000000000 +0000 @@ -31,6 +31,7 @@ struct dm_io { int error; struct bio *bio; atomic_t io_count; + unsigned long start_time; }; /* @@ -244,6 +245,42 @@ static inline void free_tio(struct mappe 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; + + preempt_disable(); + disk_round_stats(dm_disk(md)); + preempt_enable(); + dm_disk(md)->in_flight = pending = atomic_dec_return(&md->pending); + + switch (bio_data_dir(bio)) { + case WRITE: + disk_stat_add(dm_disk(md), write_ticks, duration); + break; + case READ: + disk_stat_add(dm_disk(md), read_ticks, duration); + break; + } + + return !pending; +} + /* * Add the bio to the list of deferred io. */ @@ -299,7 +336,7 @@ static inline void dec_pending(struct dm 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 +591,7 @@ static void __split_bio(struct mapped_de 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); Index: current-quilt-publish/drivers/block/ll_rw_blk.c =================================================================== --- current-quilt-publish.orig/drivers/block/ll_rw_blk.c 2006-01-03 21:08:09.000000000 +0000 +++ current-quilt-publish/drivers/block/ll_rw_blk.c 2006-01-03 21:08:23.000000000 +0000 @@ -2442,6 +2442,8 @@ void disk_round_stats(struct gendisk *di disk->stamp_idle = now; } +EXPORT_SYMBOL_GPL(disk_round_stats); + /* * queue lock must be held */