diff --git a/block/bio.c b/block/bio.c index 9d70ebe4122cf3898674851be72f1ea5f2070f12..06193e854577e1ecff96d66b4f382084ceedd2a5 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1733,8 +1733,9 @@ void update_io_ticks(int cpu, struct hd_struct *part, unsigned long now, bool en } } -void generic_start_io_acct(struct request_queue *q, int op, - unsigned long sectors, struct hd_struct *part) +static void __generic_start_io_acct(struct request_queue *q, int op, + unsigned long sectors, + struct hd_struct *part, bool precise) { const int sgrp = op_stat_group(op); int cpu = part_stat_lock(); @@ -1743,16 +1744,33 @@ void generic_start_io_acct(struct request_queue *q, int op, part_round_stats(q, cpu, part); else update_io_ticks(cpu, part, jiffies, false); - part_stat_inc(cpu, part, ios[sgrp]); - part_stat_add(cpu, part, sectors[sgrp], sectors); + if (!precise) { + part_stat_inc(cpu, part, ios[sgrp]); + part_stat_add(cpu, part, sectors[sgrp], sectors); + } part_inc_in_flight(q, part, op_is_write(op)); part_stat_unlock(); } + +void generic_start_io_acct(struct request_queue *q, int op, + unsigned long sectors, struct hd_struct *part) +{ + __generic_start_io_acct(q, op, sectors, part, false); +} EXPORT_SYMBOL(generic_start_io_acct); -void generic_end_io_acct(struct request_queue *q, int req_op, - struct hd_struct *part, unsigned long start_time) +void generic_start_precise_io_acct(struct request_queue *q, int op, + struct hd_struct *part) +{ + __generic_start_io_acct(q, op, 0, part, true); +} +EXPORT_SYMBOL(generic_start_precise_io_acct); + +static void __generic_end_io_acct(struct request_queue *q, int req_op, + struct hd_struct *part, + unsigned long start_time, + unsigned long sectors, bool precise) { unsigned long now = jiffies; unsigned long duration = now - start_time; @@ -1765,13 +1783,32 @@ void generic_end_io_acct(struct request_queue *q, int req_op, update_io_ticks(cpu, part, now, true); part_stat_add(cpu, part, time_in_queue, duration); } + if (precise) { + part_stat_inc(cpu, part, ios[sgrp]); + part_stat_add(cpu, part, sectors[sgrp], sectors); + } part_stat_add(cpu, part, nsecs[sgrp], jiffies_to_nsecs(duration)); part_dec_in_flight(q, part, op_is_write(req_op)); part_stat_unlock(); } + +void generic_end_io_acct(struct request_queue *q, int req_op, + struct hd_struct *part, unsigned long start_time) +{ + __generic_end_io_acct(q, req_op, part, start_time, 0, false); +} EXPORT_SYMBOL(generic_end_io_acct); +void generic_end_precise_io_acct(struct request_queue *q, int req_op, + struct hd_struct *part, + unsigned long start_time, + unsigned long sectors) +{ + __generic_end_io_acct(q, req_op, part, start_time, sectors, true); +} +EXPORT_SYMBOL(generic_end_precise_io_acct); + #if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE void bio_flush_dcache_pages(struct bio *bi) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0aa6fd33abf1aeece9c8f14979b573cf7b3928db..1d2ae304f09652293ad2851939293b9103d7fff1 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -621,8 +621,8 @@ static void start_io_acct(struct dm_io *io) io->start_time = jiffies; - generic_start_io_acct(md->queue, bio_op(bio), bio_sectors(bio), - &dm_disk(md)->part0); + generic_start_precise_io_acct(md->queue, bio_op(bio), + &dm_disk(md)->part0); atomic_set(&dm_disk(md)->part0.in_flight[rw], atomic_inc_return(&md->pending[rw])); @@ -640,8 +640,8 @@ static void end_io_acct(struct mapped_device *md, struct bio *bio, int pending; int rw = bio_data_dir(bio); - generic_end_io_acct(md->queue, bio_op(bio), &dm_disk(md)->part0, - start_time); + generic_end_precise_io_acct(md->queue, bio_op(bio), &dm_disk(md)->part0, + start_time, bio_sectors(bio)); if (unlikely(dm_stats_used(&md->stats))) dm_stats_account_io(&md->stats, bio_data_dir(bio), diff --git a/include/linux/bio.h b/include/linux/bio.h index 361b1bcd3debd940b68766f170785841fee82ce3..6a41b7b70d88ac240e575ca52e9159dbd2b068a0 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -497,6 +497,12 @@ void generic_start_io_acct(struct request_queue *q, int op, void generic_end_io_acct(struct request_queue *q, int op, struct hd_struct *part, unsigned long start_time); +void generic_start_precise_io_acct(struct request_queue *q, int op, + struct hd_struct *part); +void generic_end_precise_io_acct(struct request_queue *q, int op, + struct hd_struct *part, + unsigned long start_time, + unsigned long secotors); #ifndef ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE # error "You should define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE for your platform"