Commit ad620bec authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

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: default avatarDouglas Gilbert <dgilbert@interlog.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20240130214911.1863909-19-bvanassche@acm.org


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent f8ab2710
Loading
Loading
Loading
Loading
+50 −0
Original line number Diff line number Diff line
@@ -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)
{