scsi: sd_zbc: emulate ZONE_APPEND commands
[sfrench/cifs-2.6.git] / drivers / scsi / sd.c
index a793cb08d02562a2a2b92c46ec7542803644ea4b..7b0383e42b4c59a1f88f13e6bf7e4947db5149dc 100644 (file)
@@ -1206,6 +1206,12 @@ static blk_status_t sd_setup_read_write_cmnd(struct scsi_cmnd *cmd)
                }
        }
 
+       if (req_op(rq) == REQ_OP_ZONE_APPEND) {
+               ret = sd_zbc_prepare_zone_append(cmd, &lba, nr_blocks);
+               if (ret)
+                       return ret;
+       }
+
        fua = rq->cmd_flags & REQ_FUA ? 0x8 : 0;
        dix = scsi_prot_sg_count(cmd);
        dif = scsi_host_dif_capable(cmd->device->host, sdkp->protection_type);
@@ -1287,6 +1293,7 @@ static blk_status_t sd_init_command(struct scsi_cmnd *cmd)
                return sd_setup_flush_cmnd(cmd);
        case REQ_OP_READ:
        case REQ_OP_WRITE:
+       case REQ_OP_ZONE_APPEND:
                return sd_setup_read_write_cmnd(cmd);
        case REQ_OP_ZONE_RESET:
                return sd_zbc_setup_zone_mgmt_cmnd(cmd, ZO_RESET_WRITE_POINTER,
@@ -2055,7 +2062,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
 
  out:
        if (sd_is_zoned(sdkp))
-               sd_zbc_complete(SCpnt, good_bytes, &sshdr);
+               good_bytes = sd_zbc_complete(SCpnt, good_bytes, &sshdr);
 
        SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt,
                                           "sd_done: completed %d of %d bytes\n",
@@ -3372,6 +3379,10 @@ static int sd_probe(struct device *dev)
        sdkp->first_scan = 1;
        sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS;
 
+       error = sd_zbc_init_disk(sdkp);
+       if (error)
+               goto out_free_index;
+
        sd_revalidate_disk(gd);
 
        gd->flags = GENHD_FL_EXT_DEVT;
@@ -3409,6 +3420,7 @@ static int sd_probe(struct device *dev)
  out_put:
        put_disk(gd);
  out_free:
+       sd_zbc_release_disk(sdkp);
        kfree(sdkp);
  out:
        scsi_autopm_put_device(sdp);
@@ -3485,6 +3497,8 @@ static void scsi_disk_release(struct device *dev)
        put_disk(disk);
        put_device(&sdkp->device->sdev_gendev);
 
+       sd_zbc_release_disk(sdkp);
+
        kfree(sdkp);
 }