All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] null_blk cleanup and fix
@ 2020-03-30  4:01 Damien Le Moal
  2020-03-30  4:01 ` [PATCH 1/2] null_blk: Cleanup zoned device initialization Damien Le Moal
  2020-03-30  4:01 ` [PATCH 2/2] block: null_blk: Fix zoned command handling Damien Le Moal
  0 siblings, 2 replies; 7+ messages in thread
From: Damien Le Moal @ 2020-03-30  4:01 UTC (permalink / raw)
  To: linux-block, Jens Axboe; +Cc: Johannes Thumshirn

Jens,

The first patch of this series, extracted as is from Johannes series
for REQ_OP_ZONE_APPEND support cleans up null_blk zoned device
initialization. The reviewed tag from Christoph sent for the patch
within Johannes post is included here.

The second patch extracts and extends a fix included in the zonne
append series to correctly handle writes to null_blk zoned devices.
The fix forces zone type and zone condition checks to be executed
before the generic null_blk bad block and memory backing options
handling. The fix also makes sure that a zone write pointer position
is updated only if these two generic operations are executed
successfully.

Please consider these patches for inclusion in 5.7.

Damien Le Moal (2):
  null_blk: Cleanup zoned device initialization
  block: null_blk: Fix zoned command handling

 drivers/block/null_blk.h       | 37 +++++++++++++++++++++---
 drivers/block/null_blk_main.c  | 51 ++++++++++++----------------------
 drivers/block/null_blk_zoned.c | 37 ++++++++++++++++++------
 3 files changed, 79 insertions(+), 46 deletions(-)

-- 
2.25.1


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] null_blk: Cleanup zoned device initialization
  2020-03-30  4:01 [PATCH 0/2] null_blk cleanup and fix Damien Le Moal
@ 2020-03-30  4:01 ` Damien Le Moal
  2020-03-30  5:55   ` Johannes Thumshirn
  2020-03-31  8:25   ` Christoph Hellwig
  2020-03-30  4:01 ` [PATCH 2/2] block: null_blk: Fix zoned command handling Damien Le Moal
  1 sibling, 2 replies; 7+ messages in thread
From: Damien Le Moal @ 2020-03-30  4:01 UTC (permalink / raw)
  To: linux-block, Jens Axboe; +Cc: Johannes Thumshirn

Move all zoned mode related code from null_blk_main.c to
null_blk_zoned.c, avoiding an ugly #ifdef in the process.
Rename null_zone_init() into null_init_zoned_dev(), null_zone_exit()
into null_free_zoned_dev() and add the new function
null_register_zoned_dev() to finalize the zoned dev setup before
add_disk().

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 drivers/block/null_blk.h       | 14 ++++++++++----
 drivers/block/null_blk_main.c  | 27 +++++++--------------------
 drivers/block/null_blk_zoned.c | 21 +++++++++++++++++++--
 3 files changed, 36 insertions(+), 26 deletions(-)

diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h
index 62b660821dbc..2874463f1d42 100644
--- a/drivers/block/null_blk.h
+++ b/drivers/block/null_blk.h
@@ -86,8 +86,9 @@ struct nullb {
 };
 
 #ifdef CONFIG_BLK_DEV_ZONED
-int null_zone_init(struct nullb_device *dev);
-void null_zone_exit(struct nullb_device *dev);
+int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q);
+int null_register_zoned_dev(struct nullb *nullb);
+void null_free_zoned_dev(struct nullb_device *dev);
 int null_report_zones(struct gendisk *disk, sector_t sector,
 		      unsigned int nr_zones, report_zones_cb cb, void *data);
 blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
@@ -96,12 +97,17 @@ blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
 size_t null_zone_valid_read_len(struct nullb *nullb,
 				sector_t sector, unsigned int len);
 #else
-static inline int null_zone_init(struct nullb_device *dev)
+static inline int null_init_zoned_dev(struct nullb_device *dev,
+				      struct request_queue *q)
 {
 	pr_err("CONFIG_BLK_DEV_ZONED not enabled\n");
 	return -EINVAL;
 }
-static inline void null_zone_exit(struct nullb_device *dev) {}
+static inline int null_register_zoned_dev(struct nullb *nullb)
+{
+	return -ENODEV;
+}
+static inline void null_free_zoned_dev(struct nullb_device *dev) {}
 static inline blk_status_t null_handle_zoned(struct nullb_cmd *cmd,
 					     enum req_opf op, sector_t sector,
 					     sector_t nr_sectors)
diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c
index 5f13793d35ee..60f09fac6404 100644
--- a/drivers/block/null_blk_main.c
+++ b/drivers/block/null_blk_main.c
@@ -573,7 +573,7 @@ static void null_free_dev(struct nullb_device *dev)
 	if (!dev)
 		return;
 
-	null_zone_exit(dev);
+	null_free_zoned_dev(dev);
 	badblocks_exit(&dev->badblocks);
 	kfree(dev);
 }
@@ -1596,19 +1596,12 @@ static int null_gendisk_register(struct nullb *nullb)
 	disk->queue		= nullb->q;
 	strncpy(disk->disk_name, nullb->disk_name, DISK_NAME_LEN);
 
-#ifdef CONFIG_BLK_DEV_ZONED
 	if (nullb->dev->zoned) {
-		if (queue_is_mq(nullb->q)) {
-			int ret = blk_revalidate_disk_zones(disk);
-			if (ret)
-				return ret;
-		} else {
-			blk_queue_chunk_sectors(nullb->q,
-					nullb->dev->zone_size_sects);
-			nullb->q->nr_zones = blkdev_nr_zones(disk);
-		}
+		int ret = null_register_zoned_dev(nullb);
+
+		if (ret)
+			return ret;
 	}
-#endif
 
 	add_disk(disk);
 	return 0;
@@ -1764,14 +1757,9 @@ static int null_add_dev(struct nullb_device *dev)
 	}
 
 	if (dev->zoned) {
-		rv = null_zone_init(dev);
+		rv = null_init_zoned_dev(dev, nullb->q);
 		if (rv)
 			goto out_cleanup_blk_queue;
-
-		nullb->q->limits.zoned = BLK_ZONED_HM;
-		blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, nullb->q);
-		blk_queue_required_elevator_features(nullb->q,
-						ELEVATOR_F_ZBD_SEQ_WRITE);
 	}
 
 	nullb->q->queuedata = nullb;
@@ -1800,8 +1788,7 @@ static int null_add_dev(struct nullb_device *dev)
 
 	return 0;
 out_cleanup_zone:
-	if (dev->zoned)
-		null_zone_exit(dev);
+	null_free_zoned_dev(dev);
 out_cleanup_blk_queue:
 	blk_cleanup_queue(nullb->q);
 out_cleanup_tags:
diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c
index ed34785dd64b..8259f3212a28 100644
--- a/drivers/block/null_blk_zoned.c
+++ b/drivers/block/null_blk_zoned.c
@@ -10,7 +10,7 @@ static inline unsigned int null_zone_no(struct nullb_device *dev, sector_t sect)
 	return sect >> ilog2(dev->zone_size_sects);
 }
 
-int null_zone_init(struct nullb_device *dev)
+int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
 {
 	sector_t dev_size = (sector_t)dev->size * 1024 * 1024;
 	sector_t sector = 0;
@@ -58,10 +58,27 @@ int null_zone_init(struct nullb_device *dev)
 		sector += dev->zone_size_sects;
 	}
 
+	q->limits.zoned = BLK_ZONED_HM;
+	blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
+	blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE);
+
+	return 0;
+}
+
+int null_register_zoned_dev(struct nullb *nullb)
+{
+	struct request_queue *q = nullb->q;
+
+	if (queue_is_mq(q))
+		return blk_revalidate_disk_zones(nullb->disk);
+
+	blk_queue_chunk_sectors(q, nullb->dev->zone_size_sects);
+	q->nr_zones = blkdev_nr_zones(nullb->disk);
+
 	return 0;
 }
 
-void null_zone_exit(struct nullb_device *dev)
+void null_free_zoned_dev(struct nullb_device *dev)
 {
 	kvfree(dev->zones);
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] block: null_blk: Fix zoned command handling
  2020-03-30  4:01 [PATCH 0/2] null_blk cleanup and fix Damien Le Moal
  2020-03-30  4:01 ` [PATCH 1/2] null_blk: Cleanup zoned device initialization Damien Le Moal
@ 2020-03-30  4:01 ` Damien Le Moal
  2020-03-30  5:59   ` Johannes Thumshirn
  2020-03-31  8:28   ` Christoph Hellwig
  1 sibling, 2 replies; 7+ messages in thread
From: Damien Le Moal @ 2020-03-30  4:01 UTC (permalink / raw)
  To: linux-block, Jens Axboe; +Cc: Johannes Thumshirn

For writes operations issued to a null_blk device with zoned mode
enabled, the state and write pointer position of the zone targeted by
the write command should be checked before badblocks and memory backing
is handled as the write may be first failed due to, for instance, a
sector position not aligned with the zone write pointer. This als
reflects more accuratly the behavior of a physical zoned device.

Furthermore, the write pointer position of the target zone should be
incremented only and only if no errors are reported by badblocks and
memory backing handling.

To fix this, introduce the small inline helper function
null_process_cmd() which execute null_handle_badblocks() and
null_handle_memory_backed() and use this function in null_zone_write()
to correctly handle write requests to zoned null devices depending on
the type and state of the write target zone. Also call this function
in null_handle_zoned() to process read requests to zoned null devices.
This new helper is called from null_handle_cmd() only for regular null
devices, resulting in no functional change for these.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/block/null_blk.h       | 23 +++++++++++++++++++++++
 drivers/block/null_blk_main.c  | 24 ++++++++++--------------
 drivers/block/null_blk_zoned.c | 16 ++++++++++------
 3 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/drivers/block/null_blk.h b/drivers/block/null_blk.h
index 2874463f1d42..b2a0869aef47 100644
--- a/drivers/block/null_blk.h
+++ b/drivers/block/null_blk.h
@@ -85,6 +85,29 @@ struct nullb {
 	char disk_name[DISK_NAME_LEN];
 };
 
+blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
+				   sector_t sector, sector_t nr_sectors);
+blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op);
+
+static inline blk_status_t null_process_cmd(struct nullb_cmd *cmd,
+					    enum req_opf op, sector_t sector,
+					    unsigned int nr_sectors)
+{
+	struct nullb_device *dev = cmd->nq->dev;
+	blk_status_t ret;
+
+	if (dev->badblocks.shift != -1) {
+		ret = null_handle_badblocks(cmd, sector, nr_sectors);
+		if (ret != BLK_STS_OK)
+			return ret;
+	}
+
+	if (dev->memory_backed)
+		return null_handle_memory_backed(cmd, op);
+
+	return BLK_STS_OK;
+}
+
 #ifdef CONFIG_BLK_DEV_ZONED
 int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q);
 int null_register_zoned_dev(struct nullb *nullb);
diff --git a/drivers/block/null_blk_main.c b/drivers/block/null_blk_main.c
index 60f09fac6404..36bfaf1e8dbd 100644
--- a/drivers/block/null_blk_main.c
+++ b/drivers/block/null_blk_main.c
@@ -1214,9 +1214,8 @@ static inline blk_status_t null_handle_throttled(struct nullb_cmd *cmd)
 	return sts;
 }
 
-static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
-						 sector_t sector,
-						 sector_t nr_sectors)
+blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
+				   sector_t sector, sector_t nr_sectors)
 {
 	struct badblocks *bb = &cmd->nq->dev->badblocks;
 	sector_t first_bad;
@@ -1228,12 +1227,14 @@ static inline blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
 	return BLK_STS_OK;
 }
 
-static inline blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd,
-						     enum req_opf op)
+blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op)
 {
 	struct nullb_device *dev = cmd->nq->dev;
 	int err;
 
+	if (!dev->memory_backed)
+		return BLK_STS_OK;
+
 	if (dev->queue_mode == NULL_Q_BIO)
 		err = null_handle_bio(cmd);
 	else
@@ -1286,17 +1287,12 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector,
 		goto out;
 	}
 
-	if (nullb->dev->badblocks.shift != -1) {
-		cmd->error = null_handle_badblocks(cmd, sector, nr_sectors);
-		if (cmd->error != BLK_STS_OK)
-			goto out;
+	if (dev->zoned) {
+		cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
+		goto out;
 	}
 
-	if (dev->memory_backed)
-		cmd->error = null_handle_memory_backed(cmd, op);
-
-	if (!cmd->error && dev->zoned)
-		cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
+	cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);
 
 out:
 	nullb_complete_cmd(cmd);
diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c
index 8259f3212a28..c60b19432a2e 100644
--- a/drivers/block/null_blk_zoned.c
+++ b/drivers/block/null_blk_zoned.c
@@ -138,11 +138,14 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
 	struct nullb_device *dev = cmd->nq->dev;
 	unsigned int zno = null_zone_no(dev, sector);
 	struct blk_zone *zone = &dev->zones[zno];
+	blk_status_t ret;
+
+	if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
+		return null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
 
 	switch (zone->cond) {
 	case BLK_ZONE_COND_FULL:
 		/* Cannot write to a full zone */
-		cmd->error = BLK_STS_IOERR;
 		return BLK_STS_IOERR;
 	case BLK_ZONE_COND_EMPTY:
 	case BLK_ZONE_COND_IMP_OPEN:
@@ -155,17 +158,18 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
 		if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
 			zone->cond = BLK_ZONE_COND_IMP_OPEN;
 
+		ret = null_process_cmd(cmd, REQ_OP_WRITE, sector, nr_sectors);
+		if (ret != BLK_STS_OK)
+			return ret;
+
 		zone->wp += nr_sectors;
 		if (zone->wp == zone->start + zone->len)
 			zone->cond = BLK_ZONE_COND_FULL;
-		break;
-	case BLK_ZONE_COND_NOT_WP:
-		break;
+		return BLK_STS_OK;
 	default:
 		/* Invalid zone condition */
 		return BLK_STS_IOERR;
 	}
-	return BLK_STS_OK;
 }
 
 static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
@@ -236,6 +240,6 @@ blk_status_t null_handle_zoned(struct nullb_cmd *cmd, enum req_opf op,
 	case REQ_OP_ZONE_FINISH:
 		return null_zone_mgmt(cmd, op, sector);
 	default:
-		return BLK_STS_OK;
+		return null_process_cmd(cmd, op, sector, nr_sectors);
 	}
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] null_blk: Cleanup zoned device initialization
  2020-03-30  4:01 ` [PATCH 1/2] null_blk: Cleanup zoned device initialization Damien Le Moal
@ 2020-03-30  5:55   ` Johannes Thumshirn
  2020-03-31  8:25   ` Christoph Hellwig
  1 sibling, 0 replies; 7+ messages in thread
From: Johannes Thumshirn @ 2020-03-30  5:55 UTC (permalink / raw)
  To: Damien Le Moal, linux-block, Jens Axboe

Looks good,Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] block: null_blk: Fix zoned command handling
  2020-03-30  4:01 ` [PATCH 2/2] block: null_blk: Fix zoned command handling Damien Le Moal
@ 2020-03-30  5:59   ` Johannes Thumshirn
  2020-03-31  8:28   ` Christoph Hellwig
  1 sibling, 0 replies; 7+ messages in thread
From: Johannes Thumshirn @ 2020-03-30  5:59 UTC (permalink / raw)
  To: Damien Le Moal, linux-block, Jens Axboe

Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] null_blk: Cleanup zoned device initialization
  2020-03-30  4:01 ` [PATCH 1/2] null_blk: Cleanup zoned device initialization Damien Le Moal
  2020-03-30  5:55   ` Johannes Thumshirn
@ 2020-03-31  8:25   ` Christoph Hellwig
  1 sibling, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2020-03-31  8:25 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-block, Jens Axboe, Johannes Thumshirn

Doesn't this belong after the actual bug fix?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] block: null_blk: Fix zoned command handling
  2020-03-30  4:01 ` [PATCH 2/2] block: null_blk: Fix zoned command handling Damien Le Moal
  2020-03-30  5:59   ` Johannes Thumshirn
@ 2020-03-31  8:28   ` Christoph Hellwig
  1 sibling, 0 replies; 7+ messages in thread
From: Christoph Hellwig @ 2020-03-31  8:28 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-block, Jens Axboe, Johannes Thumshirn

> +blk_status_t null_handle_badblocks(struct nullb_cmd *cmd,
> +				   sector_t sector, sector_t nr_sectors);
> +blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op);
> +
> +static inline blk_status_t null_process_cmd(struct nullb_cmd *cmd,
> +					    enum req_opf op, sector_t sector,
> +					    unsigned int nr_sectors)
> +{
> +	struct nullb_device *dev = cmd->nq->dev;
> +	blk_status_t ret;
> +
> +	if (dev->badblocks.shift != -1) {
> +		ret = null_handle_badblocks(cmd, sector, nr_sectors);
> +		if (ret != BLK_STS_OK)
> +			return ret;
> +	}
> +
> +	if (dev->memory_backed)
> +		return null_handle_memory_backed(cmd, op);
> +
> +	return BLK_STS_OK;

I think this should remaing non-inlined in null_blk_main.c.

> +blk_status_t null_handle_memory_backed(struct nullb_cmd *cmd, enum req_opf op)
>  {
>  	struct nullb_device *dev = cmd->nq->dev;
>  	int err;
>  
> +	if (!dev->memory_backed)
> +		return BLK_STS_OK;

Why does this duplicate the check done in the caller?

> +	if (dev->zoned) {
> +		cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
> +		goto out;
>  	}
>  
> +	cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);

Why not:

	if (dev->zoned)
		cmd->error = null_handle_zoned(cmd, op, sector, nr_sectors);
	else
		cmd->error = null_process_cmd(cmd, op, sector, nr_sectors);

And maybe rename null_handle_zoned to null_process_zoned_cmd to keep
things symmetric.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-03-31  8:28 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-30  4:01 [PATCH 0/2] null_blk cleanup and fix Damien Le Moal
2020-03-30  4:01 ` [PATCH 1/2] null_blk: Cleanup zoned device initialization Damien Le Moal
2020-03-30  5:55   ` Johannes Thumshirn
2020-03-31  8:25   ` Christoph Hellwig
2020-03-30  4:01 ` [PATCH 2/2] block: null_blk: Fix zoned command handling Damien Le Moal
2020-03-30  5:59   ` Johannes Thumshirn
2020-03-31  8:28   ` Christoph Hellwig

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.