null_blk: Support REQ_OP_ZONE_APPEND
authorDamien Le Moal <damien.lemoal@wdc.com>
Tue, 12 May 2020 08:55:52 +0000 (17:55 +0900)
committerJens Axboe <axboe@kernel.dk>
Wed, 13 May 2020 02:36:28 +0000 (20:36 -0600)
Support REQ_OP_ZONE_APPEND requests for null_blk devices with zoned
mode enabled. Use the internally tracked zone write pointer position
as the actual write position and return it using the command request
__sector field in the case of an mq device and using the command BIO
sector in the case of a BIO device.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/block/null_blk_zoned.c

index 46641df..9c19f74 100644 (file)
@@ -70,13 +70,20 @@ int null_init_zoned_dev(struct nullb_device *dev, struct request_queue *q)
 
 int null_register_zoned_dev(struct nullb *nullb)
 {
+       struct nullb_device *dev = nullb->dev;
        struct request_queue *q = nullb->q;
 
-       if (queue_is_mq(q))
-               return blk_revalidate_disk_zones(nullb->disk, NULL);
+       if (queue_is_mq(q)) {
+               int ret = blk_revalidate_disk_zones(nullb->disk, NULL);
+
+               if (ret)
+                       return ret;
+       } else {
+               blk_queue_chunk_sectors(q, dev->zone_size_sects);
+               q->nr_zones = blkdev_nr_zones(nullb->disk);
+       }
 
-       blk_queue_chunk_sectors(q, nullb->dev->zone_size_sects);
-       q->nr_zones = blkdev_nr_zones(nullb->disk);
+       blk_queue_max_zone_append_sectors(q, dev->zone_size_sects);
 
        return 0;
 }
@@ -138,7 +145,7 @@ size_t null_zone_valid_read_len(struct nullb *nullb,
 }
 
 static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
-                    unsigned int nr_sectors)
+                                   unsigned int nr_sectors, bool append)
 {
        struct nullb_device *dev = cmd->nq->dev;
        unsigned int zno = null_zone_no(dev, sector);
@@ -158,9 +165,21 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
        case BLK_ZONE_COND_IMP_OPEN:
        case BLK_ZONE_COND_EXP_OPEN:
        case BLK_ZONE_COND_CLOSED:
-               /* Writes must be at the write pointer position */
-               if (sector != zone->wp)
+               /*
+                * Regular writes must be at the write pointer position.
+                * Zone append writes are automatically issued at the write
+                * pointer and the position returned using the request or BIO
+                * sector.
+                */
+               if (append) {
+                       sector = zone->wp;
+                       if (cmd->bio)
+                               cmd->bio->bi_iter.bi_sector = sector;
+                       else
+                               cmd->rq->__sector = sector;
+               } else if (sector != zone->wp) {
                        return BLK_STS_IOERR;
+               }
 
                if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
                        zone->cond = BLK_ZONE_COND_IMP_OPEN;
@@ -242,7 +261,9 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_opf op,
 {
        switch (op) {
        case REQ_OP_WRITE:
-               return null_zone_write(cmd, sector, nr_sectors);
+               return null_zone_write(cmd, sector, nr_sectors, false);
+       case REQ_OP_ZONE_APPEND:
+               return null_zone_write(cmd, sector, nr_sectors, true);
        case REQ_OP_ZONE_RESET:
        case REQ_OP_ZONE_RESET_ALL:
        case REQ_OP_ZONE_OPEN: