block/dm: fix bio-based DM IO accounting
Subsystems (2)
v2 cover block/dm: fix bio-based DM IO accounting
Hi Jens,
Just over 3 years ago, with commit a1e1cb72d9649 ("dm: fix redundant IO accounting for bios that need splitting") I focused too narrowly on fixing the reported potential for redundant accounting for IO totals. Which, at least mentally for me, papered over how inaccurate all other bio-based DM's IO accounting is for bios that get split.
This set fixes things up properly by allowing DM to start IO accounting _after_ IO is submitted and a split is occurred. The proper start_time is still established (prior to submission), it is passed in to a new bio_start_io_acct_time(). This eliminates the need for any DM hack to rewind block core's excessive accounting in the face of a split bio recursing back to block core.
All said: If you'd provide your Acked-by(s) I'm happy to send this set to Linus for v5.17-rc (and shepherd the changes into stable@ kernels). Or you're welcome to pickup this set to send along (I'd obviously still do any stable@ backports). NOTE: the 3rd patch references the linux-dm.git commit id for the 1st patch.. so that'll require tweaking no matter who sends the changes to Linus.
Please advise, thanks.
Mike
v1 -> v2: made block changes suggested by Christoph
Mike Snitzer (3):
block: add bio_start_io_acct_time() to control start_time
dm: revert partial fix for redundant bio-based IO accounting
dm: properly fix redundant bio-based IO accounting
block/blk-core.c | 25 +++++++++++++++++++------ drivers/md/dm.c | 20 +++----------------- include/linux/blkdev.h | 1 + 3 files changed, 23 insertions(+), 23 deletions(-)
Signature · 1 line
2.15.0
PATCH v2 1/3 block: add bio_start_io_acct_time() to control start_time
bio_start_io_acct_time() interface is like bio_start_io_acct() that allows start_time to be passed in. This gives drivers the ability to defer starting accounting until after IO is issued (but possibily not entirely due to bio splitting).
--- block/blk-core.c | 25 +++++++++++++++++++------ include/linux/blkdev.h | 1 + 2 files changed, 20 insertions(+), 6 deletions(-)
block/blk-core.c +19 -6
@@ -1061,20 +1061,32 @@ void update_io_ticks(struct block_device *part, unsigned long now, bool end) }static unsigned long __part_start_io_acct (struct block_device *part, -unsigned int sectors,unsigned int op) +unsigned int sectors,unsigned int op, +unsigned long start_time) {const int sgrp =op_stat_group (op); -unsigned long now =READ_ONCE (jiffies);part_stat_lock (); -update_io_ticks (part, now, false); +update_io_ticks (part, start_time, false);part_stat_inc (part, ios[sgrp]);part_stat_add (part, sectors[sgrp], sectors);part_stat_local_inc (part, in_flight[op_is_write (op)]);part_stat_unlock (); -return now; +return start_time; +} + +/** +* bio_start_io_acct_time - start I/O accounting for bio based drivers +* @bio: bio to start account for +* @start_time: start time that should be passed back to bio_end_io_acct(). +*/ +void bio_start_io_acct_time (struct bio *bio,unsigned long start_time) +{ +__part_start_io_acct (bio->bi_bdev,bio_sectors (bio), +bio_op (bio), start_time); } +EXPORT_SYMBOL_GPL (bio_start_io_acct_time);/** * bio_start_io_acct - start I/O accounting for bio based drivers
@@ -1084,14 +1096,15 @@ static unsigned long __part_start_io_acct(struct block_device *part,*/ unsigned long bio_start_io_acct (struct bio *bio) { -return __part_start_io_acct (bio->bi_bdev,bio_sectors (bio),bio_op (bio)); +return __part_start_io_acct (bio->bi_bdev,bio_sectors (bio), +bio_op (bio), jiffies); }EXPORT_SYMBOL_GPL (bio_start_io_acct);unsigned long disk_start_io_acct (struct gendisk *disk,unsigned int sectors,unsigned int op) { -return __part_start_io_acct (disk->part0, sectors, op); +return __part_start_io_acct (disk->part0, sectors, op, jiffies); }EXPORT_SYMBOL (disk_start_io_acct);
include/linux/blkdev.h +1 -0
@@ -1258,6 +1258,7 @@ unsigned long disk_start_io_acct(struct gendisk *disk, unsigned int sectors,void disk_end_io_acct (struct gendisk *disk,unsigned int op,unsigned long start_time); +void bio_start_io_acct_time (struct bio *bio,unsigned long start_time);unsigned long bio_start_io_acct (struct bio *bio);void bio_end_io_acct_remapped (struct bio *bio,unsigned long start_time,struct block_device *orig_bdev);
Signature · 1 line
2.15.0
PATCH v2 2/3 dm: revert partial fix for redundant bio-based IO accounting
In reply to Mike SnitzerReverts a1e1cb72d9649 ("dm: fix redundant IO accounting for bios that need splitting") because it was too narrow in scope (only addressed redundant 'sectors[]' accounting and not ios, nsecs[], etc).
--- drivers/md/dm.c | 15 --------------- 1 file changed, 15 deletions(-)
drivers/md/dm.c +0 -15
@@ -1442,9 +1442,6 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md, ci->sector = bio->bi_iter.bi_sector; } -#define __dm_part_stat_sub (part, field, subnd) \ - (part_stat_get(part, field) -= (subnd)) -/* * Entry point to split a bio into clones and submit them to the targets. */
@@ -1480,18 +1477,6 @@ static void __split_and_process_bio(struct mapped_device *md, GFP_NOIO, &md->queue->bio_split); ci.io->orig_bio = b; -/* -* Adjust IO stats for each split, otherwise upon queue -* reentry there will be redundant IO accounting. -* NOTE: this is a stop-gap fix, a proper fix involves -* significant refactoring of DM core's bio splitting -* (by eliminating DM's splitting and just using bio_split) -*/ -part_stat_lock (); -__dm_part_stat_sub (dm_disk (md)->part0, - sectors[op_stat_group (bio_op (bio))], ci.sector_count); -part_stat_unlock (); -bio_chain (b, bio);trace_block_split (b, bio->bi_iter.bi_sector);submit_bio_noacct (bio);
Signature · 1 line
2.15.0
PATCH v2 3/3 dm: properly fix redundant bio-based IO accounting
In reply to Mike SnitzerRecord the start_time for a bio but defer the starting block core's IO accounting until after IO is submitted using bio_start_io_acct_time().
This approach avoids the need to mess around with any of the individual IO stats in response to a bio_split() that follows bio submission.
Depends-on: f9893e1da2e3 ("block: add bio_start_io_acct_time() to control start_time")
--- drivers/md/dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/md/dm.c +3 -2
@@ -489,7 +489,7 @@ static void start_io_acct(struct dm_io *io)struct mapped_device *md = io->md;struct bio *bio = io->orig_bio; - io->start_time =bio_start_io_acct (bio); +__bio_start_io_acct (bio, io->start_time);if (unlikely (dm_stats_used (&md->stats))) dm_stats_account_io(&md->stats, bio_data_dir(bio), bio->bi_iter.bi_sector, bio_sectors(bio),
@@ -535,7 +535,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) io->md = md;spin_lock_init (&io->endio_lock); -start_io_acct (io); + io->start_time =READ_ONCE (jiffies);return io; }
@@ -1482,6 +1482,7 @@ static void __split_and_process_bio(struct mapped_device *md,submit_bio_noacct (bio); } } +start_io_acct (ci.io);/* drop the extra reference count */ dm_io_dec_pending (ci.io,errno_to_blk_status (error));
Signature · 1 line
2.15.0
kernel test robot
build botRe: [PATCH v2 3/3] dm: properly fix redundant bio-based IO accounting
I love your patch! Yet something to improve:
Hi Mike,
I love your patch! Yet something to improve:
[auto build test ERROR on axboe-block/for-next]
[also build test ERROR on device-mapper-dm/for-next hch-configfs/for-next v5.17-rc1 next-20220127] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Mike-Snitzer/block-dm-fix-bio-based-DM-IO-accounting/20220128-065741 base: https://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux-block.git for-next config: alpha-allmodconfig (https://download.01.org/0day-ci/archive/20220128/202201281121.YMTa5Abg-lkp(a)intel.com/config) compiler: alpha-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/8bce71c28a009209a279db6200c981596b769dd1
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Mike-Snitzer/block-dm-fix-bio-based-DM-IO-accounting/20220128-065741 git checkout 8bce71c28a009209a279db6200c981596b769dd1
# save the config file to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=alpha SHELL=/bin/bash drivers/
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
drivers/md/dm.c: In function 'start_io_acct':
>> drivers/md/dm.c:492:9: error: implicit declaration of function '__bio_start_io_acct'; did you mean 'bio_start_io_acct'? [-Werror=implicit-function-declaration]
492 | __bio_start_io_acct(bio, io->start_time);
| ^~~~~~~~~~~~~~~~~~~
| bio_start_io_acctcc1: some warnings being treated as errors
vim +492 drivers/md/dm.c
486
487 static void start_io_acct(struct dm_io *io)
488 {
489 struct mapped_device *md = io->md;
490 struct bio *bio = io->orig_bio;
491
> 492 __bio_start_io_acct(bio, io->start_time);
493 if (unlikely(dm_stats_used(&md->stats)))
494 dm_stats_account_io(&md->stats, bio_data_dir(bio),
495 bio->bi_iter.bi_sector, bio_sectors(bio),
496 false, 0, &io->stats_aux);
497 }
498
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Re: [PATCH v2 3/3] dm: properly fix redundant bio-based IO accounting
In reply to Mike SnitzerQuoted 20 lines · Mike Snitzer
Record the
start_timefor a bio but defer the starting block core's IO accounting until after IO is submitted usingbio_start_io_acct_time().This approach avoids the need to mess around with any of the individual IO stats in response to a
bio_split()that follows bio submission.Reported-by Bud Brown <[email protected]>Depends-on:
f9893e1da2e3("block: addbio_start_io_acct_time()to controlstart_time")Signed-off-by Mike Snitzer <[email protected]>--- drivers/md/dm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)drivers/md/dm.c +0
-0
drivers/md/dm.c static void start_io_acct(struct dm_io *io) · line 495
Quoted 8 lines
drivers/md/dm.c +1
-1@@ -489,7 +489,7 @@ static void start_io_acct(struct dm_io *io)struct mapped_device *md = io->md;struct bio *bio = io->orig_bio; - io->start_time =bio_start_io_acct (bio); +__bio_start_io_acct (bio, io->start_time);if (unlikely (dm_stats_used (&md->stats))) dm_stats_account_io(&md->stats, bio_data_dir(bio), bio->bi_iter.bi_sector, bio_sectors(bio),
This should be calling bio_start_io_acct_time().
I updated the header but somehow dropped the code change before sending.
Mike
Quoted 20 lines
drivers/md/dm.c +2
-1@@ -535,7 +535,7 @@ static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) io->md = md;spin_lock_init (&io->endio_lock); -start_io_acct (io); + io->start_time =READ_ONCE (jiffies);return io; }@@ -1482,6 +1482,7 @@ static void __split_and_process_bio(struct mapped_device *md,submit_bio_noacct (bio); } } +start_io_acct (ci.io);/* drop the extra reference count */ dm_io_dec_pending (ci.io,errno_to_blk_status (error));Signature · 1 line
2.15.0