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 with different target type. Signed-off-by: Yang Yang <yang.yang@xxxxxxxx> --- drivers/md/dm.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 25215b93c3cf..9dbddc214084 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_target *ti; /* * Use an on-stack bio for this, it's safe since we don't @@ -1574,10 +1575,21 @@ 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++) { + ti = dm_table_get_target(t, i); + __send_empty_flush_bios(t, ti, ci); + } + } else { + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *dd; - __send_empty_flush_bios(t, ti, ci); + list_for_each_entry(dd, devices, list) { + struct list_head *targets = &dd->dm_dev->targets; + + list_for_each_entry(ti, targets, list) + __send_empty_flush_bios(t, ti, ci); + } } /* -- 2.34.1