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 linan122@huawei.com --- include/linux/bio.h | 6 ++++++ block/bio.c | 47 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/include/linux/bio.h b/include/linux/bio.h index 361b1bcd3deb..9ad329b8591f 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, + unsigned long sectors, 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" diff --git a/block/bio.c b/block/bio.c index 9d70ebe4122c..7b70cae809a5 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) +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,32 @@ 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, + unsigned long sectors, struct hd_struct *part) +{ + __generic_start_io_acct(q, op, 0, part, true); +} +EXPORT_SYMBOL(generic_start_precise_io_acct); + +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 +1782,31 @@ 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) {