From: hotforest <hotforest@gmail.com> hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/10302 -------------------------------- Advertise P2PDMA only when every target in a table remaps bio data without CPU access, and every underlying device advertises P2PDMA. Reevaluate the queue flag on table activation so that mixed or reloaded tables cannot accept unsupported P2PDMA pages. - Define the DM_TARGET_PCI_P2PDMA target feature. A target sets this feature when it passes bio data to its underlying devices without CPU access to the data pages. The feature uses an unused target feature bit and changes no public structure. - Mark the linear and striped targets with this feature. Their data paths remap or split bios. They do not read or transform data pages. - dm_table_set_restrictions() sets QUEUE_FLAG_PCI_P2PDMA on the mapped device queue only when all targets in the table have the feature and all their underlying devices advertise the flag. Otherwise it clears the flag. A mixed table stays unsupported. - Other targets, including dm-crypt and dm-raid, do not set the feature. They keep the flag cleared. Signed-off-by: hotforest <hotforest@gmail.com> Signed-off-by: Zizhi Wo <wozizhi@huawei.com> --- drivers/md/dm-linear.c | 3 ++- drivers/md/dm-stripe.c | 3 ++- drivers/md/dm-table.c | 26 ++++++++++++++++++++++++++ include/linux/device-mapper.h | 5 +++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index f4448d520ee9..1cf4812a5614 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -198,11 +198,12 @@ static size_t linear_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff, static struct target_type linear_target = { .name = "linear", .version = {1, 4, 0}, .features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_NOWAIT | - DM_TARGET_ZONED_HM | DM_TARGET_PASSES_CRYPTO, + DM_TARGET_ZONED_HM | DM_TARGET_PASSES_CRYPTO | + DM_TARGET_PCI_P2PDMA, .report_zones = linear_report_zones, .module = THIS_MODULE, .ctr = linear_ctr, .dtr = linear_dtr, .map = linear_map, diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index efc289c3a573..b56f5478a1e2 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -466,11 +466,12 @@ static void stripe_io_hints(struct dm_target *ti, } static struct target_type stripe_target = { .name = "striped", .version = {1, 6, 0}, - .features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_NOWAIT, + .features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_NOWAIT | + DM_TARGET_PCI_P2PDMA, .module = THIS_MODULE, .ctr = stripe_ctr, .dtr = stripe_dtr, .map = stripe_map, .end_io = stripe_end_io, diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index ed0a5e91968d..6dfe6ec08133 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1564,10 +1564,31 @@ static bool dm_table_supports_poll(struct dm_table *t) } return true; } +static int device_not_pci_p2pdma_capable(struct dm_target *ti, + struct dm_dev *dev, sector_t start, sector_t len, void *data) +{ + return !blk_queue_pci_p2pdma(bdev_get_queue(dev->bdev)); +} + +static bool dm_table_supports_pci_p2pdma(struct dm_table *t) +{ + for (unsigned int i = 0; i < t->num_targets; i++) { + struct dm_target *ti = dm_table_get_target(t, i); + + if (!dm_target_supports_pci_p2pdma(ti->type) || + !ti->type->iterate_devices || + ti->type->iterate_devices(ti, + device_not_pci_p2pdma_capable, NULL)) + return false; + } + + return t->num_targets > 0; +} + /* * Check whether a table has no data devices attached using each * target's iterate_devices method. * Returns false if the result is unknown because a target doesn't * support iterate_devices. @@ -1961,10 +1982,15 @@ int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, if (dm_table_supports_nowait(t)) blk_queue_flag_set(QUEUE_FLAG_NOWAIT, q); else blk_queue_flag_clear(QUEUE_FLAG_NOWAIT, q); + if (dm_table_supports_pci_p2pdma(t)) + blk_queue_flag_set(QUEUE_FLAG_PCI_P2PDMA, q); + else + blk_queue_flag_clear(QUEUE_FLAG_PCI_P2PDMA, q); + if (!dm_table_supports_discards(t)) { q->limits.max_discard_sectors = 0; q->limits.max_hw_discard_sectors = 0; q->limits.discard_granularity = 0; q->limits.discard_alignment = 0; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 772ab4d74d94..4dc7d21e1d8d 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -292,10 +292,15 @@ struct target_type { #else #define DM_TARGET_MIXED_ZONED_MODEL 0x00000000 #define dm_target_supports_mixed_zoned_model(type) (false) #endif +/* Target passes bio data to its underlying devices without CPU access. */ +#define DM_TARGET_PCI_P2PDMA 0x00000400 +#define dm_target_supports_pci_p2pdma(type) \ + ((type)->features & DM_TARGET_PCI_P2PDMA) + struct dm_target { struct dm_table *table; struct target_type *type; /* target limits */ -- 2.52.0