From 30cc50ffea347778f5e12ab89e629cd22bcc4aff Mon Sep 17 00:00:00 2001 From: Li Nan Date: Wed, 6 Sep 2023 10:48:17 +0800 Subject: [PATCH 1/2] block: add precise io accouting apis hulk inclusion category: bugfix bugzilla: 188421, https://gitee.com/openeuler/kernel/issues/I7WMMI CVE: NA -------------------------------- Currently, for bio-based device, 'ios' and 'sectors' is counted while io is started, while 'nsecs' is counted while io is done. This behaviour is obviously wrong, however we can't fix exist kapis because this will require new parameter, which will cause kapi broken. Hence this patch add some new apis, which will make sure io accounting for bio-based device is precise. Signed-off-by: Li Nan --- block/bio.c | 49 +++++++++++++++++++++++++++++++++++++++------ include/linux/bio.h | 6 ++++++ 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/block/bio.c b/block/bio.c index 9d70ebe4122c..06193e854577 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/include/linux/bio.h b/include/linux/bio.h index 361b1bcd3deb..6a41b7b70d88 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" -- Gitee From 434e1bea8a77c35733d233ea7b301cb49505c612 Mon Sep 17 00:00:00 2001 From: Li Nan Date: Wed, 6 Sep 2023 10:48:18 +0800 Subject: [PATCH 2/2] dm: switch to precise io accounting hulk inclusion category: bugfix bugzilla: 188421, https://gitee.com/openeuler/kernel/issues/I7WMMI CVE: NA -------------------------------- 'ios' and 'sectors' is counted in bio_start_io_acct() while io is started insted of io is done. Hence switch to precise io accounting to count them when io is done. Signed-off-by: Li Nan --- drivers/md/dm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 0aa6fd33abf1..1d2ae304f096 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), -- Gitee