scsi: scsi_debug: Implement GET STREAM STATUS

Implement the GET STREAM STATUS SCSI command. Report that the first
five stream indexes correspond to permanent streams.

Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Douglas Gilbert <dgilbert@interlog.com>
Tested-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-19-bvanassche@acm.org
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Bart Van Assche 2024-01-30 13:48:44 -08:00 committed by Martin K. Petersen
parent f8ab271017
commit ad620becda

View file

@ -533,6 +533,8 @@ static int resp_write_scat(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_get_stream_status(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip);
static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
static int resp_rsup_opcodes(struct scsi_cmnd *, struct sdebug_dev_info *);
@ -607,6 +609,9 @@ static const struct opcode_info_t sa_in_16_iarr[] = {
{0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
{16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0, 0xc7} }, /* GET LBA STATUS(16) */
{0, 0x9e, 0x16, F_SA_LOW | F_D_IN, resp_get_stream_status, NULL,
{16, 0x16, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff,
0, 0} }, /* GET STREAM STATUS */
};
static const struct opcode_info_t vl_iarr[] = { /* VARIABLE LENGTH */
@ -4573,6 +4578,51 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
}
static int resp_get_stream_status(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip)
{
u16 starting_stream_id, stream_id;
const u8 *cmd = scp->cmnd;
u32 alloc_len, offset;
u8 arr[256] = {};
struct scsi_stream_status_header *h = (void *)arr;
starting_stream_id = get_unaligned_be16(cmd + 4);
alloc_len = get_unaligned_be32(cmd + 10);
if (alloc_len < 8) {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
return check_condition_result;
}
if (starting_stream_id >= MAXIMUM_NUMBER_OF_STREAMS) {
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
return check_condition_result;
}
/*
* The GET STREAM STATUS command only reports status information
* about open streams. Treat the non-permanent stream as open.
*/
put_unaligned_be16(MAXIMUM_NUMBER_OF_STREAMS,
&h->number_of_open_streams);
for (offset = 8, stream_id = starting_stream_id;
offset + 8 <= min_t(u32, alloc_len, sizeof(arr)) &&
stream_id < MAXIMUM_NUMBER_OF_STREAMS;
offset += 8, stream_id++) {
struct scsi_stream_status *stream_status = (void *)arr + offset;
stream_status->perm = stream_id < PERMANENT_STREAM_COUNT;
put_unaligned_be16(stream_id,
&stream_status->stream_identifier);
stream_status->rel_lifetime = stream_id + 1;
}
put_unaligned_be32(offset - 8, &h->len); /* PARAMETER DATA LENGTH */
return fill_from_dev_buffer(scp, arr, min(offset, alloc_len));
}
static int resp_sync_cache(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip)
{