All of lore.kernel.org
 help / color / mirror / Atom feed
From: Damien Le Moal <damien.lemoal@wdc.com>
To: dm-devel@redhat.com, Mike Snitzer <snitzer@redhat.com>,
	linux-block@vger.kernel.org, Jens Axboe <axboe@kernel.dk>
Subject: [PATCH v2 08/11] dm: Forbid requeue of writes to zones
Date: Thu, 20 May 2021 13:22:25 +0900	[thread overview]
Message-ID: <20210520042228.974083-9-damien.lemoal@wdc.com> (raw)
In-Reply-To: <20210520042228.974083-1-damien.lemoal@wdc.com>

A target map method requesting the requeue of a bio with
DM_MAPIO_REQUEUE or completing it with DM_ENDIO_REQUEUE can cause
unaligned write errors if the bio is a write operation targeting a
sequential zone. If a zoned target request such a requeue, warn about
it and kill the IO.

The function dm_is_zone_write() is introduced to detect write operations
to zoned targets.

This change does not affect the target drivers supporting zoned devices
and exposing a zoned device, namely dm-crypt, dm-linear and dm-flakey as
none of these targets ever request a requeue.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/md/dm-zone.c | 17 +++++++++++++++++
 drivers/md/dm.c      | 18 +++++++++++++++---
 drivers/md/dm.h      |  5 +++++
 3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index b42474043249..edc3bbb45637 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -104,6 +104,23 @@ int dm_report_zones(struct block_device *bdev, sector_t start, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(dm_report_zones);
 
+bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
+{
+	struct request_queue *q = md->queue;
+
+	if (!blk_queue_is_zoned(q))
+		return false;
+
+	switch (bio_op(bio)) {
+	case REQ_OP_WRITE_ZEROES:
+	case REQ_OP_WRITE_SAME:
+	case REQ_OP_WRITE:
+		return !op_is_flush(bio->bi_opf) && bio_sectors(bio);
+	default:
+		return false;
+	}
+}
+
 void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
 {
 	if (!blk_queue_is_zoned(q))
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 45d2dc2ee844..4426019a89cc 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -846,11 +846,15 @@ static void dec_pending(struct dm_io *io, blk_status_t error)
 			 * Target requested pushing back the I/O.
 			 */
 			spin_lock_irqsave(&md->deferred_lock, flags);
-			if (__noflush_suspending(md))
+			if (__noflush_suspending(md) &&
+			    !WARN_ON_ONCE(dm_is_zone_write(md, bio)))
 				/* NOTE early return due to BLK_STS_DM_REQUEUE below */
 				bio_list_add_head(&md->deferred, io->orig_bio);
 			else
-				/* noflush suspend was interrupted. */
+				/*
+				 * noflush suspend was interrupted or this is
+				 * a write to a zoned target.
+				 */
 				io->status = BLK_STS_IOERR;
 			spin_unlock_irqrestore(&md->deferred_lock, flags);
 		}
@@ -947,7 +951,15 @@ static void clone_endio(struct bio *bio)
 		int r = endio(tio->ti, bio, &error);
 		switch (r) {
 		case DM_ENDIO_REQUEUE:
-			error = BLK_STS_DM_REQUEUE;
+			/*
+			 * Requeuing writes to a sequential zone of a zoned
+			 * target will break the sequential write pattern:
+			 * fail such IO.
+			 */
+			if (WARN_ON_ONCE(dm_is_zone_write(md, bio)))
+				error = BLK_STS_IOERR;
+			else
+				error = BLK_STS_DM_REQUEUE;
 			fallthrough;
 		case DM_ENDIO_DONE:
 			break;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index fdf1536a4b62..39c243258e24 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -107,8 +107,13 @@ void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q);
 #ifdef CONFIG_BLK_DEV_ZONED
 int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
 			unsigned int nr_zones, report_zones_cb cb, void *data);
+bool dm_is_zone_write(struct mapped_device *md, struct bio *bio);
 #else
 #define dm_blk_report_zones	NULL
+static inline bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
+{
+	return false;
+}
 #endif
 
 /*-----------------------------------------------------------------
-- 
2.31.1


WARNING: multiple messages have this Message-ID (diff)
From: Damien Le Moal <damien.lemoal@wdc.com>
To: dm-devel@redhat.com, Mike Snitzer <snitzer@redhat.com>,
	linux-block@vger.kernel.org, Jens Axboe <axboe@kernel.dk>
Subject: [dm-devel] [PATCH v2 08/11] dm: Forbid requeue of writes to zones
Date: Thu, 20 May 2021 13:22:25 +0900	[thread overview]
Message-ID: <20210520042228.974083-9-damien.lemoal@wdc.com> (raw)
In-Reply-To: <20210520042228.974083-1-damien.lemoal@wdc.com>

A target map method requesting the requeue of a bio with
DM_MAPIO_REQUEUE or completing it with DM_ENDIO_REQUEUE can cause
unaligned write errors if the bio is a write operation targeting a
sequential zone. If a zoned target request such a requeue, warn about
it and kill the IO.

The function dm_is_zone_write() is introduced to detect write operations
to zoned targets.

This change does not affect the target drivers supporting zoned devices
and exposing a zoned device, namely dm-crypt, dm-linear and dm-flakey as
none of these targets ever request a requeue.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/md/dm-zone.c | 17 +++++++++++++++++
 drivers/md/dm.c      | 18 +++++++++++++++---
 drivers/md/dm.h      |  5 +++++
 3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-zone.c b/drivers/md/dm-zone.c
index b42474043249..edc3bbb45637 100644
--- a/drivers/md/dm-zone.c
+++ b/drivers/md/dm-zone.c
@@ -104,6 +104,23 @@ int dm_report_zones(struct block_device *bdev, sector_t start, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(dm_report_zones);
 
+bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
+{
+	struct request_queue *q = md->queue;
+
+	if (!blk_queue_is_zoned(q))
+		return false;
+
+	switch (bio_op(bio)) {
+	case REQ_OP_WRITE_ZEROES:
+	case REQ_OP_WRITE_SAME:
+	case REQ_OP_WRITE:
+		return !op_is_flush(bio->bi_opf) && bio_sectors(bio);
+	default:
+		return false;
+	}
+}
+
 void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
 {
 	if (!blk_queue_is_zoned(q))
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 45d2dc2ee844..4426019a89cc 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -846,11 +846,15 @@ static void dec_pending(struct dm_io *io, blk_status_t error)
 			 * Target requested pushing back the I/O.
 			 */
 			spin_lock_irqsave(&md->deferred_lock, flags);
-			if (__noflush_suspending(md))
+			if (__noflush_suspending(md) &&
+			    !WARN_ON_ONCE(dm_is_zone_write(md, bio)))
 				/* NOTE early return due to BLK_STS_DM_REQUEUE below */
 				bio_list_add_head(&md->deferred, io->orig_bio);
 			else
-				/* noflush suspend was interrupted. */
+				/*
+				 * noflush suspend was interrupted or this is
+				 * a write to a zoned target.
+				 */
 				io->status = BLK_STS_IOERR;
 			spin_unlock_irqrestore(&md->deferred_lock, flags);
 		}
@@ -947,7 +951,15 @@ static void clone_endio(struct bio *bio)
 		int r = endio(tio->ti, bio, &error);
 		switch (r) {
 		case DM_ENDIO_REQUEUE:
-			error = BLK_STS_DM_REQUEUE;
+			/*
+			 * Requeuing writes to a sequential zone of a zoned
+			 * target will break the sequential write pattern:
+			 * fail such IO.
+			 */
+			if (WARN_ON_ONCE(dm_is_zone_write(md, bio)))
+				error = BLK_STS_IOERR;
+			else
+				error = BLK_STS_DM_REQUEUE;
 			fallthrough;
 		case DM_ENDIO_DONE:
 			break;
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index fdf1536a4b62..39c243258e24 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -107,8 +107,13 @@ void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q);
 #ifdef CONFIG_BLK_DEV_ZONED
 int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
 			unsigned int nr_zones, report_zones_cb cb, void *data);
+bool dm_is_zone_write(struct mapped_device *md, struct bio *bio);
 #else
 #define dm_blk_report_zones	NULL
+static inline bool dm_is_zone_write(struct mapped_device *md, struct bio *bio)
+{
+	return false;
+}
 #endif
 
 /*-----------------------------------------------------------------
-- 
2.31.1

--
dm-devel mailing list
dm-devel@redhat.com
https://listman.redhat.com/mailman/listinfo/dm-devel


  parent reply	other threads:[~2021-05-20  4:22 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-20  4:22 [PATCH v2 00/11] dm: Improve zoned block device support Damien Le Moal
2021-05-20  4:22 ` [dm-devel] " Damien Le Moal
2021-05-20  4:22 ` [PATCH v2 01/11] block: improve handling of all zones reset operation Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:49   ` Hannes Reinecke
2021-05-20  5:49     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 02/11] block: introduce bio zone helpers Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:50   ` Hannes Reinecke
2021-05-20  5:50     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 03/11] block: introduce BIO_ZONE_WRITE_LOCKED bio flag Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:52   ` Hannes Reinecke
2021-05-20  5:52     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 04/11] dm: Fix dm_accept_partial_bio() Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:53   ` Hannes Reinecke
2021-05-20  5:53     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 05/11] dm: cleanup device_area_is_invalid() Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:53   ` Hannes Reinecke
2021-05-20  5:53     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 06/11] dm: move zone related code to dm-zone.c Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:54   ` Hannes Reinecke
2021-05-20  5:54     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 07/11] dm: Introduce dm_report_zones() Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:56   ` Hannes Reinecke
2021-05-20  5:56     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` Damien Le Moal [this message]
2021-05-20  4:22   ` [dm-devel] [PATCH v2 08/11] dm: Forbid requeue of writes to zones Damien Le Moal
2021-05-20  5:57   ` Hannes Reinecke
2021-05-20  5:57     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 09/11] dm: rearrange core declarations Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  5:59   ` Hannes Reinecke
2021-05-20  5:59     ` [dm-devel] " Hannes Reinecke
2021-05-20  4:22 ` [PATCH v2 10/11] dm: introduce zone append emulation Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  6:10   ` Hannes Reinecke
2021-05-20  6:10     ` [dm-devel] " Hannes Reinecke
2021-05-20  6:25     ` Damien Le Moal
2021-05-20  6:25       ` [dm-devel] " Damien Le Moal
2021-05-20  6:47       ` Hannes Reinecke
2021-05-20  6:47         ` [dm-devel] " Hannes Reinecke
2021-05-20  6:57         ` Damien Le Moal
2021-05-20  6:57           ` [dm-devel] " Damien Le Moal
2021-05-20  4:22 ` [PATCH v2 11/11] dm crypt: Fix zoned block device support Damien Le Moal
2021-05-20  4:22   ` [dm-devel] " Damien Le Moal
2021-05-20  6:11   ` Hannes Reinecke
2021-05-20  6:11     ` [dm-devel] " Hannes Reinecke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210520042228.974083-9-damien.lemoal@wdc.com \
    --to=damien.lemoal@wdc.com \
    --cc=axboe@kernel.dk \
    --cc=dm-devel@redhat.com \
    --cc=linux-block@vger.kernel.org \
    --cc=snitzer@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.