If the num_targets is greater than the number of dm_devs in the dm_table's devices list, __send_empty_flush() might invoke __send_duplicate_bios() multiple times for the same block device. This could lead to a substantial decrease in performance when num_targets significantly exceeds the number of dm_devs. This patch ensure that __send_duplicate_bios() is only called once for each dm_dev. Signed-off-by: Yang Yang <yang.yang@xxxxxxxx> --- drivers/md/dm.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 25215b93c3cf..9dd0f5c97028 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1561,6 +1561,7 @@ static void __send_empty_flush(struct clone_info *ci) { struct dm_table *t = ci->map; struct bio flush_bio; + struct dm_dev_internal *dd; /* * Use an on-stack bio for this, it's safe since we don't @@ -1574,10 +1575,18 @@ static void __send_empty_flush(struct clone_info *ci) ci->sector_count = 0; ci->io->tio.clone.bi_iter.bi_size = 0; - for (unsigned int i = 0; i < t->num_targets; i++) { - struct dm_target *ti = dm_table_get_target(t, i); + if (!t->flush_pass_around) { + for (unsigned int i = 0; i < t->num_targets; i++) { + struct dm_target *ti = dm_table_get_target(t, i); + __send_empty_flush_bios(t, ti, ci); + } + } else { + down_read(&t->devices_lock); + + list_for_each_entry(dd, dm_table_get_devices(t), list) + __send_empty_flush_bios(t, dd->dm_dev->ti, ci); - __send_empty_flush_bios(t, ti, ci); + up_read(&t->devices_lock); } /* -- 2.34.1