@@ -1999,6 +1999,37 @@ static int device_requires_stable_pages(struct dm_target *ti,
return blk_queue_stable_writes(q);
}
+#ifdef CONFIG_BLK_DEV_ZONED
+static int device_not_zone_append_capable(struct dm_target *ti,
+ struct dm_dev *dev, sector_t start,
+ sector_t len, void *data)
+{
+ struct request_queue *q = bdev_get_queue(dev->bdev);
+
+ return !blk_queue_is_zoned(q) ||
+ !q->limits.max_zone_append_sectors;
+}
+
+static bool dm_table_supports_zone_append(struct dm_table *t)
+{
+ struct dm_target *ti;
+ unsigned int i;
+
+ for (i = 0; i < dm_table_get_num_targets(t); i++) {
+ ti = dm_table_get_target(t, i);
+
+ if (ti->zone_append_not_supported)
+ return false;
+
+ if (!ti->type->iterate_devices ||
+ ti->type->iterate_devices(ti, device_not_zone_append_capable, NULL))
+ return false;
+ }
+
+ return true;
+}
+#endif
+
void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
struct queue_limits *limits)
{
@@ -2091,6 +2122,16 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
if (blk_queue_is_zoned(q)) {
WARN_ON_ONCE(queue_is_mq(q));
q->nr_zones = blkdev_nr_zones(t->md->disk);
+
+ /*
+ * All zoned devices support zone append by default. However,
+ * some zoned targets (e.g. dm-crypt) cannot support this
+ * operation. Check here if the target indicated the lack of
+ * support for zone append and set max_zone_append_sectors to 0
+ * in that case so that users (e.g. an FS) can detect this fact.
+ */
+ if (!dm_table_supports_zone_append(t))
+ q->limits.max_zone_append_sectors = 0;
}
#endif
@@ -361,6 +361,12 @@ struct dm_target {
* Set if we need to limit the number of in-flight bios when swapping.
*/
bool limit_swap_bios:1;
+
+ /*
+ * Set if this target is a zoned device that cannot accept
+ * zone append operations.
+ */
+ bool zone_append_not_supported:1;
};
void *dm_per_bio_data(struct bio *bio, size_t data_size);