Skip to content

Commit ad620be

Browse files
bvanasschemartinkpetersen
authored andcommitted
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>
1 parent f8ab271 commit ad620be

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

drivers/scsi/scsi_debug.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ static int resp_write_scat(struct scsi_cmnd *, struct sdebug_dev_info *);
533533
static int resp_start_stop(struct scsi_cmnd *, struct sdebug_dev_info *);
534534
static int resp_readcap16(struct scsi_cmnd *, struct sdebug_dev_info *);
535535
static int resp_get_lba_status(struct scsi_cmnd *, struct sdebug_dev_info *);
536+
static int resp_get_stream_status(struct scsi_cmnd *scp,
537+
struct sdebug_dev_info *devip);
536538
static int resp_report_tgtpgs(struct scsi_cmnd *, struct sdebug_dev_info *);
537539
static int resp_unmap(struct scsi_cmnd *, struct sdebug_dev_info *);
538540
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[] = {
607609
{0, 0x9e, 0x12, F_SA_LOW | F_D_IN, resp_get_lba_status, NULL,
608610
{16, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
609611
0xff, 0xff, 0xff, 0, 0xc7} }, /* GET LBA STATUS(16) */
612+
{0, 0x9e, 0x16, F_SA_LOW | F_D_IN, resp_get_stream_status, NULL,
613+
{16, 0x16, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff,
614+
0, 0} }, /* GET STREAM STATUS */
610615
};
611616

612617
static const struct opcode_info_t vl_iarr[] = { /* VARIABLE LENGTH */
@@ -4573,6 +4578,51 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
45734578
return fill_from_dev_buffer(scp, arr, SDEBUG_GET_LBA_STATUS_LEN);
45744579
}
45754580

4581+
static int resp_get_stream_status(struct scsi_cmnd *scp,
4582+
struct sdebug_dev_info *devip)
4583+
{
4584+
u16 starting_stream_id, stream_id;
4585+
const u8 *cmd = scp->cmnd;
4586+
u32 alloc_len, offset;
4587+
u8 arr[256] = {};
4588+
struct scsi_stream_status_header *h = (void *)arr;
4589+
4590+
starting_stream_id = get_unaligned_be16(cmd + 4);
4591+
alloc_len = get_unaligned_be32(cmd + 10);
4592+
4593+
if (alloc_len < 8) {
4594+
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 10, -1);
4595+
return check_condition_result;
4596+
}
4597+
4598+
if (starting_stream_id >= MAXIMUM_NUMBER_OF_STREAMS) {
4599+
mk_sense_invalid_fld(scp, SDEB_IN_CDB, 4, -1);
4600+
return check_condition_result;
4601+
}
4602+
4603+
/*
4604+
* The GET STREAM STATUS command only reports status information
4605+
* about open streams. Treat the non-permanent stream as open.
4606+
*/
4607+
put_unaligned_be16(MAXIMUM_NUMBER_OF_STREAMS,
4608+
&h->number_of_open_streams);
4609+
4610+
for (offset = 8, stream_id = starting_stream_id;
4611+
offset + 8 <= min_t(u32, alloc_len, sizeof(arr)) &&
4612+
stream_id < MAXIMUM_NUMBER_OF_STREAMS;
4613+
offset += 8, stream_id++) {
4614+
struct scsi_stream_status *stream_status = (void *)arr + offset;
4615+
4616+
stream_status->perm = stream_id < PERMANENT_STREAM_COUNT;
4617+
put_unaligned_be16(stream_id,
4618+
&stream_status->stream_identifier);
4619+
stream_status->rel_lifetime = stream_id + 1;
4620+
}
4621+
put_unaligned_be32(offset - 8, &h->len); /* PARAMETER DATA LENGTH */
4622+
4623+
return fill_from_dev_buffer(scp, arr, min(offset, alloc_len));
4624+
}
4625+
45764626
static int resp_sync_cache(struct scsi_cmnd *scp,
45774627
struct sdebug_dev_info *devip)
45784628
{

0 commit comments

Comments
 (0)