[PATCH v2 2/6] sd, sd_zbc: use scsi_cmnd cdb access functions

Douglas Gilbert
2022-04-10T17:37:06Z

Although currently unlikely to be needed, allow the sd driver to
issue SCSI commands whose CDB length is > 32. Remove the
direct access to the scsi_cmnd::cmnd field and use an access
function instead. Use 'cdb' rather than 'cmd' to refer to the
SCSI CDB field.

Signed-off-by: Douglas Gilbert <dgilbert@interlog.com>
---
drivers/scsi/sd.c | 176 +++++++++++++++++++++++-------------------
drivers/scsi/sd_zbc.c | 12 +--
2 files changed, 101 insertions(+), 87 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a390679cf458..f0fc5789ccbf 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -842,6 +842,7 @@ static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
unsigned int data_len = 24;
char *buf;
+ u8 *cdb;

rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
if (!rq->special_vec.bv_page)
@@ -851,9 +852,9 @@ static blk_status_t sd_setup_unmap_cmnd(struct scsi_cmnd *cmd)
rq->special_vec.bv_len = data_len;
rq->rq_flags |= RQF_SPECIAL_PAYLOAD;

- cmd->cmd_len = 10;
- cmd->cmnd[0] = UNMAP;
- cmd->cmnd[8] = 24;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+ cdb[0] = UNMAP;
+ cdb[8] = 24;

buf = bvec_virt(&rq->special_vec);
put_unaligned_be16(6 + 16, &buf[0]);
@@ -877,6 +878,7 @@ static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
u32 data_len = sdp->sector_size;
+ u8 *cdb;

rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
if (!rq->special_vec.bv_page)
@@ -886,12 +888,12 @@ static blk_status_t sd_setup_write_same16_cmnd(struct scsi_cmnd *cmd,
rq->special_vec.bv_len = data_len;
rq->rq_flags |= RQF_SPECIAL_PAYLOAD;

- cmd->cmd_len = 16;
- cmd->cmnd[0] = WRITE_SAME_16;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+ cdb[0] = WRITE_SAME_16;
if (unmap)
- cmd->cmnd[1] = 0x8; /* UNMAP */
- put_unaligned_be64(lba, &cmd->cmnd[2]);
- put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
+ cdb[1] = 0x8; /* UNMAP */
+ put_unaligned_be64(lba, &cdb[2]);
+ put_unaligned_be32(nr_blocks, &cdb[10]);

cmd->allowed = sdkp->max_retries;
cmd->transfersize = data_len;
@@ -909,6 +911,7 @@ static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
u64 lba = sectors_to_logical(sdp, blk_rq_pos(rq));
u32 nr_blocks = sectors_to_logical(sdp, blk_rq_sectors(rq));
u32 data_len = sdp->sector_size;
+ u8 *cdb;

rq->special_vec.bv_page = mempool_alloc(sd_page_pool, GFP_ATOMIC);
if (!rq->special_vec.bv_page)
@@ -918,12 +921,12 @@ static blk_status_t sd_setup_write_same10_cmnd(struct scsi_cmnd *cmd,
rq->special_vec.bv_len = data_len;
rq->rq_flags |= RQF_SPECIAL_PAYLOAD;

- cmd->cmd_len = 10;
- cmd->cmnd[0] = WRITE_SAME;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+ cdb[0] = WRITE_SAME;
if (unmap)
- cmd->cmnd[1] = 0x8; /* UNMAP */
- put_unaligned_be32(lba, &cmd->cmnd[2]);
- put_unaligned_be16(nr_blocks, &cmd->cmnd[7]);
+ cdb[1] = 0x8; /* UNMAP */
+ put_unaligned_be32(lba, &cdb[2]);
+ put_unaligned_be16(nr_blocks, &cdb[7]);

cmd->allowed = sdkp->max_retries;
cmd->transfersize = data_len;
@@ -1024,12 +1027,13 @@ static blk_status_t sd_setup_flush_cmnd(struct scsi_cmnd *cmd)
{
struct request *rq = scsi_cmd_to_rq(cmd);
struct scsi_disk *sdkp = scsi_disk(rq->q->disk);
+ u8 *cdb;

/* flush requests don't perform I/O, zero the S/G table */
memset(&cmd->sdb, 0, sizeof(cmd->sdb));

- cmd->cmnd[0] = SYNCHRONIZE_CACHE;
- cmd->cmd_len = 10;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+ cdb[0] = SYNCHRONIZE_CACHE;
cmd->transfersize = 0;
cmd->allowed = sdkp->max_retries;

@@ -1041,14 +1045,16 @@ static blk_status_t sd_setup_rw32_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
unsigned char flags)
{
- cmd->cmd_len = SD_EXT_CDB_SIZE;
- cmd->cmnd[0] = VARIABLE_LENGTH_CMD;
- cmd->cmnd[7] = 0x18; /* Additional CDB len */
- cmd->cmnd[9] = write ? WRITE_32 : READ_32;
- cmd->cmnd[10] = flags;
- put_unaligned_be64(lba, &cmd->cmnd[12]);
- put_unaligned_be32(lba, &cmd->cmnd[20]); /* Expected Indirect LBA */
- put_unaligned_be32(nr_blocks, &cmd->cmnd[28]);
+ u8 *cdb;
+
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, SD_EXT_CDB_SIZE);
+ cdb[0] = VARIABLE_LENGTH_CMD;
+ cdb[7] = 0x18; /* Additional CDB len */
+ cdb[9] = write ? WRITE_32 : READ_32;
+ cdb[10] = flags;
+ put_unaligned_be64(lba, &cdb[12]);
+ put_unaligned_be32(lba, &cdb[20]); /* Expected Indirect LBA */
+ put_unaligned_be32(nr_blocks, &cdb[28]);

return BLK_STS_OK;
}
@@ -1057,13 +1063,15 @@ static blk_status_t sd_setup_rw16_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
unsigned char flags)
{
- cmd->cmd_len = 16;
- cmd->cmnd[0] = write ? WRITE_16 : READ_16;
- cmd->cmnd[1] = flags;
- cmd->cmnd[14] = 0;
- cmd->cmnd[15] = 0;
- put_unaligned_be64(lba, &cmd->cmnd[2]);
- put_unaligned_be32(nr_blocks, &cmd->cmnd[10]);
+ u8 *cdb;
+
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+ cdb[0] = write ? WRITE_16 : READ_16;
+ cdb[1] = flags;
+ cdb[14] = 0;
+ cdb[15] = 0;
+ put_unaligned_be64(lba, &cdb[2]);
+ put_unaligned_be32(nr_blocks, &cdb[10]);

return BLK_STS_OK;
}
@@ -1072,13 +1080,15 @@ static blk_status_t sd_setup_rw10_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
unsigned char flags)
{
- cmd->cmd_len = 10;
- cmd->cmnd[0] = write ? WRITE_10 : READ_10;
- cmd->cmnd[1] = flags;
- cmd->cmnd[6] = 0;
- cmd->cmnd[9] = 0;
- put_unaligned_be32(lba, &cmd->cmnd[2]);
- put_unaligned_be16(nr_blocks, &cmd->cmnd[7]);
+ u8 *cdb;
+
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 10);
+ cdb[0] = write ? WRITE_10 : READ_10;
+ cdb[1] = flags;
+ cdb[6] = 0;
+ cdb[9] = 0;
+ put_unaligned_be32(lba, &cdb[2]);
+ put_unaligned_be16(nr_blocks, &cdb[7]);

return BLK_STS_OK;
}
@@ -1087,6 +1097,8 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
sector_t lba, unsigned int nr_blocks,
unsigned char flags)
{
+ u8 *cdb;
+
/* Avoid that 0 blocks gets translated into 256 blocks. */
if (WARN_ON_ONCE(nr_blocks == 0))
return BLK_STS_IOERR;
@@ -1101,13 +1113,13 @@ static blk_status_t sd_setup_rw6_cmnd(struct scsi_cmnd *cmd, bool write,
return BLK_STS_IOERR;
}

- cmd->cmd_len = 6;
- cmd->cmnd[0] = write ? WRITE_6 : READ_6;
- cmd->cmnd[1] = (lba >> 16) & 0x1f;
- cmd->cmnd[2] = (lba >> 8) & 0xff;
- cmd->cmnd[3] = lba & 0xff;
- cmd->cmnd[4] = nr_blocks;
- cmd->cmnd[5] = 0;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 6);
+ cdb[0] = write ? WRITE_6 : READ_6;
+ cdb[1] = (lba >> 16) & 0x1f;
+ cdb[2] = (lba >> 8) & 0xff;
+ cdb[3] = lba & 0xff;
+ cdb[4] = nr_blocks;
+ cdb[5] = 0;

return BLK_STS_OK;
}
@@ -1589,14 +1601,14 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
sshdr = &my_sshdr;

for (retries = 3; retries > 0; --retries) {
- unsigned char cmd[10] = { 0 };
+ unsigned char cdb[10] = { 0 };

- cmd[0] = SYNCHRONIZE_CACHE;
+ cdb[0] = SYNCHRONIZE_CACHE;
/*
* Leave the rest of the command zero to indicate
* flush everything.
*/
- res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, sshdr,
+ res = scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL, sshdr,
timeout, sdkp->max_retries, 0, RQF_PM, NULL);
if (res == 0)
break;
@@ -1710,19 +1722,19 @@ static int sd_pr_command(struct block_device *bdev, u8 sa,
struct scsi_device *sdev = sdkp->device;
struct scsi_sense_hdr sshdr;
int result;
- u8 cmd[16] = { 0, };
+ u8 cdb[16] = { 0, };
u8 data[24] = { 0, };

- cmd[0] = PERSISTENT_RESERVE_OUT;
- cmd[1] = sa;
- cmd[2] = type;
- put_unaligned_be32(sizeof(data), &cmd[5]);
+ cdb[0] = PERSISTENT_RESERVE_OUT;
+ cdb[1] = sa;
+ cdb[2] = type;
+ put_unaligned_be32(sizeof(data), &cdb[5]);

put_unaligned_be64(key, &data[0]);
put_unaligned_be64(sa_key, &data[8]);
data[20] = flags;

- result = scsi_execute_req(sdev, cmd, DMA_TO_DEVICE, &data, sizeof(data),
+ result = scsi_execute_req(sdev, cdb, DMA_TO_DEVICE, &data, sizeof(data),
&sshdr, SD_TIMEOUT, sdkp->max_retries, NULL);

if (scsi_status_is_check_condition(result) &&
@@ -1931,6 +1943,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
struct scsi_sense_hdr sshdr;
struct request *req = scsi_cmd_to_rq(SCpnt);
struct scsi_disk *sdkp = scsi_disk(req->q->disk);
+ const u8 *cdb;
int sense_valid = 0;
int sense_deferred = 0;

@@ -1979,6 +1992,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
(!sense_valid || sense_deferred))
goto out;

+ cdb = scsi_cmnd_get_cdb(SCpnt);
switch (sshdr.sense_key) {
case HARDWARE_ERROR:
case MEDIUM_ERROR:
@@ -2006,13 +2020,13 @@ static int sd_done(struct scsi_cmnd *SCpnt)
break;
case 0x20: /* INVALID COMMAND OPCODE */
case 0x24: /* INVALID FIELD IN CDB */
- switch (SCpnt->cmnd[0]) {
+ switch (cdb[0]) {
case UNMAP:
sd_config_discard(sdkp, SD_LBP_DISABLE);
break;
case WRITE_SAME_16:
case WRITE_SAME:
- if (SCpnt->cmnd[1] & 8) { /* UNMAP */
+ if (cdb[1] & 8) { /* UNMAP */
sd_config_discard(sdkp, SD_LBP_DISABLE);
} else {
sdkp->device->no_write_same = 1;
@@ -2044,7 +2058,7 @@ static int sd_done(struct scsi_cmnd *SCpnt)
static void
sd_spinup_disk(struct scsi_disk *sdkp)
{
- unsigned char cmd[10];
+ u8 cdb[10];
unsigned long spintime_expire = 0;
int retries, spintime;
unsigned int the_result;
@@ -2061,10 +2075,10 @@ sd_spinup_disk(struct scsi_disk *sdkp)
do {
bool media_was_present = sdkp->media_present;

- cmd[0] = TEST_UNIT_READY;
- memset((void *) &cmd[1], 0, 9);
+ cdb[0] = TEST_UNIT_READY;
+ memset((void *) &cdb[1], 0, 9);

- the_result = scsi_execute_req(sdkp->device, cmd,
+ the_result = scsi_execute_req(sdkp->device, cdb,
DMA_NONE, NULL, 0,
&sshdr, SD_TIMEOUT,
sdkp->max_retries, NULL);
@@ -2118,13 +2132,13 @@ sd_spinup_disk(struct scsi_disk *sdkp)
*/
if (!spintime) {
sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
- cmd[0] = START_STOP;
- cmd[1] = 1; /* Return immediately */
- memset((void *) &cmd[2], 0, 8);
- cmd[4] = 1; /* Start spin cycle */
+ cdb[0] = START_STOP;
+ cdb[1] = 1; /* Return immediately */
+ memset((void *) &cdb[2], 0, 8);
+ cdb[4] = 1; /* Start spin cycle */
if (sdkp->device->start_stop_pwr_cond)
- cmd[4] |= 1 << 4;
- scsi_execute_req(sdkp->device, cmd, DMA_NONE,
+ cdb[4] |= 1 << 4;
+ scsi_execute_req(sdkp->device, cdb, DMA_NONE,
NULL, 0, &sshdr,
SD_TIMEOUT, sdkp->max_retries,
NULL);
@@ -2247,7 +2261,7 @@ static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
- unsigned char cmd[16];
+ u8 cdb[16];
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
@@ -2260,13 +2274,13 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
return -EINVAL;

do {
- memset(cmd, 0, 16);
- cmd[0] = SERVICE_ACTION_IN_16;
- cmd[1] = SAI_READ_CAPACITY_16;
- cmd[13] = RC16_LEN;
+ memset(cdb, 0, 16);
+ cdb[0] = SERVICE_ACTION_IN_16;
+ cdb[1] = SAI_READ_CAPACITY_16;
+ cdb[13] = RC16_LEN;
memset(buffer, 0, RC16_LEN);

- the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ the_result = scsi_execute_req(sdp, cdb, DMA_FROM_DEVICE,
buffer, RC16_LEN, &sshdr,
SD_TIMEOUT, sdkp->max_retries, NULL);

@@ -2338,7 +2352,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned char *buffer)
{
- unsigned char cmd[16];
+ unsigned char cdb[16];
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
int the_result;
@@ -2347,11 +2361,11 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
unsigned sector_size;

do {
- cmd[0] = READ_CAPACITY;
- memset(&cmd[1], 0, 9);
+ cdb[0] = READ_CAPACITY;
+ memset(&cdb[1], 0, 9);
memset(buffer, 0, 8);

- the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ the_result = scsi_execute_req(sdp, cdb, DMA_FROM_DEVICE,
buffer, 8, &sshdr,
SD_TIMEOUT, sdkp->max_retries, NULL);

@@ -3546,21 +3560,21 @@ static void scsi_disk_release(struct device *dev)

static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
{
- unsigned char cmd[6] = { START_STOP }; /* START_VALID */
+ u8 cdb[6] = { START_STOP }; /* START_VALID */
struct scsi_sense_hdr sshdr;
struct scsi_device *sdp = sdkp->device;
int res;

if (start)
- cmd[4] |= 1; /* START */
+ cdb[4] |= 1; /* START */

if (sdp->start_stop_pwr_cond)
- cmd[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */
+ cdb[4] |= start ? 1 << 4 : 3 << 4; /* Active or Standby */

if (!scsi_device_online(sdp))
return -ENODEV;

- res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+ res = scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL, &sshdr,
SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
if (res) {
sd_print_result(sdkp, "Start/Stop Unit failed", res);
@@ -3700,9 +3714,9 @@ static int sd_resume_runtime(struct device *dev)

if (sdp->ignore_media_change) {
/* clear the device's sense data */
- static const u8 cmd[10] = { REQUEST_SENSE };
+ static const u8 cdb[10] = { REQUEST_SENSE };

- if (scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL,
+ if (scsi_execute(sdp, cdb, DMA_NONE, NULL, 0, NULL,
NULL, sdp->request_queue->rq_timeout, 1, 0,
RQF_PM, NULL))
sd_printk(KERN_NOTICE, sdkp,
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 7f466280993b..5567e6af5b49 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -389,6 +389,7 @@ blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
struct request *rq = scsi_cmd_to_rq(cmd);
sector_t sector = blk_rq_pos(rq);
struct scsi_disk *sdkp = scsi_disk(rq->q->disk);
+ u8 *cdb;
sector_t block = sectors_to_logical(sdkp->device, sector);
blk_status_t ret;

@@ -396,14 +397,13 @@ blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
if (ret != BLK_STS_OK)
return ret;

- cmd->cmd_len = 16;
- memset(cmd->cmnd, 0, cmd->cmd_len);
- cmd->cmnd[0] = ZBC_OUT;
- cmd->cmnd[1] = op;
+ cdb = scsi_cmnd_set_cdb(cmd, NULL, 16);
+ cdb[0] = ZBC_OUT;
+ cdb[1] = op;
if (all)
- cmd->cmnd[14] = 0x1;
+ cdb[14] = 0x1;
else
- put_unaligned_be64(block, &cmd->cmnd[2]);
+ put_unaligned_be64(block, &cdb[2]);

rq->timeout = SD_TIMEOUT;
cmd->sc_data_direction = DMA_NONE;
--
2.25.1