Allow handling of bios with REQ_ATOMIC flag set.

In crypt_io_hints(), the max atomic write sizes needs to be limited
according to the max of DM_CRYPT_DEFAULT_MAX_WRITE_SIZE and max_write_size.
Otherwise, we may need to split bios in crypt_map() ->
dm_accept_partial_bio().

Signed-off-by: John Garry <[email protected]>
---
 drivers/md/dm-crypt.c | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 5ef43231fe77f..c4c97f57bc477 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -3515,8 +3515,11 @@ static int crypt_map(struct dm_target *ti, struct bio 
*bio)
         * Check if bio is too large, split as needed.
         */
        max_sectors = get_max_request_sectors(ti, bio);
-       if (unlikely(bio_sectors(bio) > max_sectors))
+       if (unlikely(bio_sectors(bio) > max_sectors)) {
+               if (bio->bi_opf & REQ_ATOMIC)
+                       return DM_MAPIO_KILL;
                dm_accept_partial_bio(bio, max_sectors);
+       }
 
        /*
         * Ensure that bio is a multiple of internal sector encryption size
@@ -3744,6 +3747,8 @@ static int crypt_iterate_devices(struct dm_target *ti,
 static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct crypt_config *cc = ti->private;
+       unsigned int _max_write_size =
+               min_not_zero(max_write_size, DM_CRYPT_DEFAULT_MAX_WRITE_SIZE);
 
        limits->logical_block_size =
                max_t(unsigned int, limits->logical_block_size, 
cc->sector_size);
@@ -3762,6 +3767,18 @@ static void crypt_io_hints(struct dm_target *ti, struct 
queue_limits *limits)
        if (ti->emulate_zone_append)
                limits->max_hw_sectors = min(limits->max_hw_sectors,
                                             BIO_MAX_VECS << 
PAGE_SECTORS_SHIFT);
+
+       if (_max_write_size < limits->atomic_write_hw_unit_min) {
+               limits->atomic_write_hw_unit_min = 0;
+               limits->atomic_write_hw_unit_max = 0;
+               limits->atomic_write_hw_max = 0;
+               limits->atomic_write_hw_boundary = 0;
+       } else {
+               limits->atomic_write_hw_unit_max =
+                       min(limits->atomic_write_hw_unit_max, _max_write_size);
+               limits->atomic_write_hw_max =
+                       min(limits->atomic_write_hw_max, _max_write_size);
+       }
 }
 
 static struct target_type crypt_target = {
@@ -3770,7 +3787,7 @@ static struct target_type crypt_target = {
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
-       .features = DM_TARGET_ZONED_HM,
+       .features = DM_TARGET_ZONED_HM | DM_TARGET_ATOMIC_WRITES,
        .report_zones = crypt_report_zones,
        .map    = crypt_map,
        .status = crypt_status,
-- 
2.43.5


Reply via email to