scsi: sd_zbc: add zone open, close, and finish support
authorAjay Joshi <ajay.joshi@wdc.com>
Sun, 27 Oct 2019 14:05:47 +0000 (23:05 +0900)
committerJens Axboe <axboe@kernel.dk>
Thu, 7 Nov 2019 13:46:02 +0000 (06:46 -0700)
Implement REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE and REQ_OP_ZONE_FINISH
support to allow explicit control of zone states.

Contains contributions from Matias Bjorling, Hans Holmberg,
Keith Busch and Damien Le Moal.

Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ajay Joshi <ajay.joshi@wdc.com>
Signed-off-by: Matias Bjorling <matias.bjorling@wdc.com>
Signed-off-by: Hans Holmberg <hans.holmberg@wdc.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/sd_zbc.c

index ebb40160539f52e1c6ee65802fb9dd731868ed89..470ee6dc3f7eb382f4bcc791f9b9ff49c0c621ff 100644 (file)
@@ -1291,9 +1291,17 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd)
        case REQ_OP_WRITE:
                return sd_setup_read_write_cmnd(cmd);
        case REQ_OP_ZONE_RESET:
-               return sd_zbc_setup_reset_cmnd(cmd, false);
+               return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER,
+                                                  false);
        case REQ_OP_ZONE_RESET_ALL:
-               return sd_zbc_setup_reset_cmnd(cmd, true);
+               return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER,
+                                                  true);
+       case REQ_OP_ZONE_OPEN:
+               return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_OPEN_ZONE, false);
+       case REQ_OP_ZONE_CLOSE:
+               return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_CLOSE_ZONE, false);
+       case REQ_OP_ZONE_FINISH:
+               return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_FINISH_ZONE, false);
        default:
                WARN_ON_ONCE(1);
                return BLK_STS_NOTSUPP;
@@ -1961,6 +1969,9 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        case REQ_OP_WRITE_SAME:
        case REQ_OP_ZONE_RESET:
        case REQ_OP_ZONE_RESET_ALL:
+       case REQ_OP_ZONE_OPEN:
+       case REQ_OP_ZONE_CLOSE:
+       case REQ_OP_ZONE_FINISH:
                if (!result) {
                        good_bytes = blk_rq_bytes(req);
                        scsi_set_resid(SCpnt, 0);
index 1eab779f812b60570ed6775e2adf8bd8edbddac9..bf2102a749bc7997b404a92a93fb7c081283d0d2 100644 (file)
@@ -209,7 +209,8 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)
 
 extern int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
 extern void sd_zbc_print_zones(struct scsi_disk *sdkp);
-extern blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all);
+blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+                                        unsigned char op, bool all);
 extern void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
                            struct scsi_sense_hdr *sshdr);
 extern int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
@@ -225,8 +226,9 @@ static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
 
 static inline void sd_zbc_print_zones(struct scsi_disk *sdkp) {}
 
-static inline blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd,
-                                                  bool all)
+static inline blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+                                                      unsigned char op,
+                                                      bool all)
 {
        return BLK_STS_TARGET;
 }
index 1efc69e194f8e06a231b0501d405ac563541adc8..39f10ec0dfcfdd21eeb77c8f30266505f87bce07 100644 (file)
@@ -207,13 +207,17 @@ static inline sector_t sd_zbc_zone_sectors(struct scsi_disk *sdkp)
 }
 
 /**
- * sd_zbc_setup_reset_cmnd - Prepare a RESET WRITE POINTER scsi command.
+ * sd_zbc_setup_zone_mgmt_cmnd - Prepare a zone ZBC_OUT command. The operations
+ *                     can be RESET WRITE POINTER, OPEN, CLOSE or FINISH.
  * @cmd: the command to setup
- * @all: Reset all zones control.
+ * @op: Operation to be performed
+ * @all: All zones control
  *
- * Called from sd_init_command() for a REQ_OP_ZONE_RESET request.
+ * Called from sd_init_command() for REQ_OP_ZONE_RESET, REQ_OP_ZONE_RESET_ALL,
+ * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE or REQ_OP_ZONE_FINISH requests.
  */
-blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all)
+blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
+                                        unsigned char op, bool all)
 {
        struct request *rq = cmd->request;
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
@@ -234,7 +238,7 @@ blk_status_t sd_zbc_setup_reset_cmnd(struct scsi_cmnd *cmd, bool all)
        cmd->cmd_len = 16;
        memset(cmd->cmnd, 0, cmd->cmd_len);
        cmd->cmnd[0] = ZBC_OUT;
-       cmd->cmnd[1] = ZO_RESET_WRITE_POINTER;
+       cmd->cmnd[1] = op;
        if (all)
                cmd->cmnd[14] = 0x1;
        else
@@ -263,14 +267,14 @@ void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
        int result = cmd->result;
        struct request *rq = cmd->request;
 
-       if (req_op(rq) == REQ_OP_ZONE_RESET &&
+       if (op_is_zone_mgmt(req_op(rq)) &&
            result &&
            sshdr->sense_key == ILLEGAL_REQUEST &&
            sshdr->asc == 0x24) {
                /*
-                * INVALID FIELD IN CDB error: reset of a conventional
-                * zone was attempted. Nothing to worry about, so be
-                * quiet about the error.
+                * INVALID FIELD IN CDB error: a zone management command was
+                * attempted on a conventional zone. Nothing to worry about,
+                * so be quiet about the error.
                 */
                rq->rq_flags |= RQF_QUIET;
        }