diff mbox series

[v1,4/7] scsi: scsi_debug: Add read support and update locate for tapes

Message ID 20250210191232.185207-5-Kai.Makisara@kolumbus.fi (mailing list archive)
State Superseded
Headers show
Series scsi: scsi_debug: Add more tape support | expand

Commit Message

Kai Mäkisara Feb. 10, 2025, 7:12 p.m. UTC
Support for the READ (6) and SPACE (6) commands for tapes based on the
previous write patch is added. The LOCATE (10) command is updated to use
the written data.

Signed-off-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi>
---
 drivers/scsi/scsi_debug.c | 240 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 235 insertions(+), 5 deletions(-)

Comments

kernel test robot Feb. 11, 2025, 3:50 p.m. UTC | #1
Hi Kai,

kernel test robot noticed the following build warnings:

[auto build test WARNING on jejb-scsi/for-next]
[also build test WARNING on mkp-scsi/for-next linus/master v6.14-rc2 next-20250210]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kai-M-kisara/scsi-scsi_debug-First-fixes-for-tapes/20250211-031623
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
patch link:    https://lore.kernel.org/r/20250210191232.185207-5-Kai.Makisara%40kolumbus.fi
patch subject: [PATCH v1 4/7] scsi: scsi_debug: Add read support and update locate for tapes
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20250211/202502112330.2jlgUZM7-lkp@intel.com/config)
compiler: clang version 19.1.3 (https://github.com/llvm/llvm-project ab51eccf88f5321e7c60591c5546b254b6afab99)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250211/202502112330.2jlgUZM7-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202502112330.2jlgUZM7-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/scsi/scsi_debug.c:31:
   In file included from include/linux/scatterlist.h:8:
   In file included from include/linux/mm.h:2224:
   include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     504 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     505 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     511 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     512 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:524:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     524 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     525 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   drivers/scsi/scsi_debug.c:2989:3: warning: variable 'len' is uninitialized when used here [-Wuninitialized]
    2989 |                 len += resp_partition_m_pg(ap, pcontrol, target);
         |                 ^~~
   drivers/scsi/scsi_debug.c:2854:28: note: initialize the variable 'len' to silence this warning
    2854 |         u32 alloc_len, offset, len;
         |                                   ^
         |                                    = 0
>> drivers/scsi/scsi_debug.c:3419:8: warning: variable 'i' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    3419 |                         if (pos == 0)
         |                             ^~~~~~~~
   drivers/scsi/scsi_debug.c:3478:44: note: uninitialized use occurs here
    3478 |                         BEGINNING_OF_P_M_DETECTED_ASCQ, count - i,
         |                                                                 ^
   drivers/scsi/scsi_debug.c:3419:4: note: remove the 'if' if its condition is always false
    3419 |                         if (pos == 0)
         |                         ^~~~~~~~~~~~~
    3420 |                                 goto is_bop;
         |                                 ~~~~~~~~~~~~
    3421 |                         else {
         |                         ~~~~
   drivers/scsi/scsi_debug.c:3378:7: note: initialize the variable 'i' to silence this warning
    3378 |         int i, pos, count;
         |              ^
         |               = 0
   drivers/scsi/scsi_debug.c:3513:10: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
    3513 |         for ( ; i < TAPE_MAX_PARTITIONS; i++)
         |                 ^
   drivers/scsi/scsi_debug.c:3502:7: note: initialize the variable 'i' to silence this warning
    3502 |         int i;
         |              ^
         |               = 0
   6 warnings generated.


vim +3419 drivers/scsi/scsi_debug.c

  3373	
  3374	static int resp_space(struct scsi_cmnd *scp,
  3375			struct sdebug_dev_info *devip)
  3376	{
  3377		unsigned char *cmd = scp->cmnd, code;
  3378		int i, pos, count;
  3379		struct tape_block *blp;
  3380		int partition = devip->tape_partition;
  3381	
  3382		count = get_unaligned_be24(cmd + 2);
  3383		if ((count & 0x800000) != 0) /* extend negative to 32-bit count */
  3384			count |= 0xff000000;
  3385		code = cmd[1] & 0x0f;
  3386	
  3387		pos = devip->tape_location[partition];
  3388		if (code == 0) { /* blocks */
  3389			if (count < 0) {
  3390				count = (-count);
  3391				pos -= 1;
  3392				for (i = 0, blp = devip->tape_blocks[partition] + pos; i < count;
  3393				     i++) {
  3394					if (pos < 0)
  3395						goto is_bop;
  3396					else if (IS_TAPE_BLOCK_FM(blp->fl_size))
  3397						goto is_fm;
  3398					if (i > 0) {
  3399						pos--;
  3400						blp--;
  3401					}
  3402				}
  3403			} else if (count > 0) {
  3404				for (i = 0, blp = devip->tape_blocks[partition] + pos; i < count;
  3405				     i++, pos++, blp++) {
  3406					if (IS_TAPE_BLOCK_EOD(blp->fl_size))
  3407						goto is_eod;
  3408					if (IS_TAPE_BLOCK_FM(blp->fl_size)) {
  3409						pos += 1;
  3410						goto is_fm;
  3411					}
  3412					if (pos >= devip->tape_eop[partition])
  3413						goto is_eop;
  3414				}
  3415			}
  3416		} else if (code == 1) { /* filemarks */
  3417			if (count < 0) {
  3418				count = (-count);
> 3419				if (pos == 0)
  3420					goto is_bop;
  3421				else {
  3422					for (i = 0, blp = devip->tape_blocks[partition] + pos;
  3423					     i < count && pos >= 0; i++, pos--, blp--) {
  3424						for (pos--, blp-- ; !IS_TAPE_BLOCK_FM(blp->fl_size) &&
  3425							     pos >= 0; pos--, blp--)
  3426							; /* empty */
  3427						if (pos < 0)
  3428							goto is_bop;
  3429					}
  3430				}
  3431				pos += 1;
  3432			} else if (count > 0) {
  3433				for (i = 0, blp = devip->tape_blocks[partition] + pos;
  3434				     i < count; i++, pos++, blp++) {
  3435					for ( ; !IS_TAPE_BLOCK_FM(blp->fl_size) &&
  3436						      !IS_TAPE_BLOCK_EOD(blp->fl_size) &&
  3437						      pos < devip->tape_eop[partition];
  3438					      pos++, blp++)
  3439						; /* empty */
  3440					if (IS_TAPE_BLOCK_EOD(blp->fl_size))
  3441						goto is_eod;
  3442					if (pos >= devip->tape_eop[partition])
  3443						goto is_eop;
  3444				}
  3445			}
  3446		} else if (code == 3) { /* EOD */
  3447			for (blp = devip->tape_blocks[partition] + pos;
  3448			     !IS_TAPE_BLOCK_EOD(blp->fl_size) && pos < devip->tape_eop[partition];
  3449			     pos++, blp++)
  3450				; /* empty */
  3451			if (pos >= devip->tape_eop[partition])
  3452				goto is_eop;
  3453		} else {
  3454			/* sequential filemarks not supported */
  3455			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, -1);
  3456			return check_condition_result;
  3457		}
  3458		devip->tape_location[partition] = pos;
  3459		return 0;
  3460	
  3461	is_fm:
  3462		devip->tape_location[partition] = pos;
  3463		mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
  3464				FILEMARK_DETECTED_ASCQ, count - i,
  3465				SENSE_FLAG_FILEMARK);
  3466		return check_condition_result;
  3467	
  3468	is_eod:
  3469		devip->tape_location[partition] = pos;
  3470		mk_sense_info_tape(scp, BLANK_CHECK, NO_ADDITIONAL_SENSE,
  3471				EOD_DETECTED_ASCQ, count - i,
  3472				0);
  3473		return check_condition_result;
  3474	
  3475	is_bop:
  3476		devip->tape_location[partition] = 0;
  3477		mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
  3478				BEGINNING_OF_P_M_DETECTED_ASCQ, count - i,
  3479				SENSE_FLAG_EOM);
  3480		devip->tape_location[partition] = 0;
  3481		return check_condition_result;
  3482	
  3483	is_eop:
  3484		devip->tape_location[partition] = devip->tape_eop[partition] - 1;
  3485		mk_sense_info_tape(scp, MEDIUM_ERROR, NO_ADDITIONAL_SENSE,
  3486				EOP_EOM_DETECTED_ASCQ, (unsigned int)i,
  3487				SENSE_FLAG_EOM);
  3488		return check_condition_result;
  3489	}
  3490
diff mbox series

Patch

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6282f162ed5a..691b573b105b 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -532,7 +532,8 @@  enum sdeb_opcode_index {
 	SDEB_I_READ_BLOCK_LIMITS = 33,
 	SDEB_I_LOCATE = 34,
 	SDEB_I_WRITE_FILEMARKS = 35,
-	SDEB_I_LAST_ELEM_P1 = 36,	/* keep this last (previous + 1) */
+	SDEB_I_SPACE = 36,
+	SDEB_I_LAST_ELEM_P1 = 37,	/* keep this last (previous + 1) */
 };
 
 
@@ -541,7 +542,7 @@  static const unsigned char opcode_ind_arr[256] = {
 	SDEB_I_TEST_UNIT_READY, SDEB_I_REZERO_UNIT, 0, SDEB_I_REQUEST_SENSE,
 	    0, SDEB_I_READ_BLOCK_LIMITS, 0, 0,
 	SDEB_I_READ, 0, SDEB_I_WRITE, 0, 0, 0, 0, 0,
-	SDEB_I_WRITE_FILEMARKS, 0, SDEB_I_INQUIRY, 0, 0,
+	SDEB_I_WRITE_FILEMARKS, SDEB_I_SPACE, SDEB_I_INQUIRY, 0, 0,
 	    SDEB_I_MODE_SELECT, SDEB_I_RESERVE, SDEB_I_RELEASE,
 	0, 0, SDEB_I_MODE_SENSE, SDEB_I_START_STOP, 0, SDEB_I_SEND_DIAG,
 	    SDEB_I_ALLOW_REMOVAL, 0,
@@ -625,6 +626,7 @@  static int resp_rwp_zone(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_read_blklimits(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_locate(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_write_filemarks(struct scsi_cmnd *, struct sdebug_dev_info *);
+static int resp_space(struct scsi_cmnd *, struct sdebug_dev_info *);
 static int resp_rewind(struct scsi_cmnd *, struct sdebug_dev_info *);
 
 static int sdebug_do_add_host(bool mk_new_store);
@@ -872,10 +874,12 @@  static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
 	{0, 0x05, 0, F_D_IN, resp_read_blklimits, NULL,    /* READ BLOCK LIMITS (6) */
 	    {6,  0, 0, 0, 0, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 	{0, 0x2b, 0, F_D_UNKN, resp_locate, NULL,    /* LOCATE (10) */
-	    {10,  0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,
+	    {10,  0x07, 0, 0xff, 0xff, 0xff, 0xff, 0, 0xff, 0xc7, 0, 0,
 	     0, 0, 0, 0} },
 	{0, 0x10, 0, F_D_IN, resp_write_filemarks, NULL,    /* WRITE FILEMARKS (6) */
 	    {6,  0x01, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
+	{0, 0x11, 0, F_D_IN, resp_space, NULL,    /* SPACE (6) */
+	    {6,  0x07, 0xff, 0xff, 0xff, 0xc7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
 
 /* sentinel */
 	{0xff, 0, 0, 0, NULL, NULL,		/* terminating element */
@@ -3309,6 +3313,9 @@  static int resp_locate(struct scsi_cmnd *scp,
 		struct sdebug_dev_info *devip)
 {
 	unsigned char *cmd = scp->cmnd;
+	unsigned int i, pos;
+	struct tape_block *blp;
+	int partition;
 
 	if ((cmd[1] & 0x02) != 0) {
 		if (cmd[8] >= devip->tape_nbr_partitions) {
@@ -3317,8 +3324,19 @@  static int resp_locate(struct scsi_cmnd *scp,
 		}
 		devip->tape_partition = cmd[8];
 	}
-	devip->tape_location[devip->tape_partition] =
-		get_unaligned_be32(cmd + 3);
+	pos = get_unaligned_be32(cmd + 3);
+	partition = devip->tape_partition;
+
+	for (i = 0, blp = devip->tape_blocks[partition];
+	     i < pos && i < devip->tape_eop[partition]; i++, blp++)
+		if (IS_TAPE_BLOCK_EOD(blp->fl_size))
+			break;
+	if (i < pos) {
+		devip->tape_location[partition] = i;
+		mk_sense_buffer(scp, BLANK_CHECK, 0x05, 0);
+		return check_condition_result;
+	}
+	devip->tape_location[partition] = pos;
 
 	return 0;
 }
@@ -3353,6 +3371,123 @@  static int resp_write_filemarks(struct scsi_cmnd *scp,
 	return 0;
 }
 
+static int resp_space(struct scsi_cmnd *scp,
+		struct sdebug_dev_info *devip)
+{
+	unsigned char *cmd = scp->cmnd, code;
+	int i, pos, count;
+	struct tape_block *blp;
+	int partition = devip->tape_partition;
+
+	count = get_unaligned_be24(cmd + 2);
+	if ((count & 0x800000) != 0) /* extend negative to 32-bit count */
+		count |= 0xff000000;
+	code = cmd[1] & 0x0f;
+
+	pos = devip->tape_location[partition];
+	if (code == 0) { /* blocks */
+		if (count < 0) {
+			count = (-count);
+			pos -= 1;
+			for (i = 0, blp = devip->tape_blocks[partition] + pos; i < count;
+			     i++) {
+				if (pos < 0)
+					goto is_bop;
+				else if (IS_TAPE_BLOCK_FM(blp->fl_size))
+					goto is_fm;
+				if (i > 0) {
+					pos--;
+					blp--;
+				}
+			}
+		} else if (count > 0) {
+			for (i = 0, blp = devip->tape_blocks[partition] + pos; i < count;
+			     i++, pos++, blp++) {
+				if (IS_TAPE_BLOCK_EOD(blp->fl_size))
+					goto is_eod;
+				if (IS_TAPE_BLOCK_FM(blp->fl_size)) {
+					pos += 1;
+					goto is_fm;
+				}
+				if (pos >= devip->tape_eop[partition])
+					goto is_eop;
+			}
+		}
+	} else if (code == 1) { /* filemarks */
+		if (count < 0) {
+			count = (-count);
+			if (pos == 0)
+				goto is_bop;
+			else {
+				for (i = 0, blp = devip->tape_blocks[partition] + pos;
+				     i < count && pos >= 0; i++, pos--, blp--) {
+					for (pos--, blp-- ; !IS_TAPE_BLOCK_FM(blp->fl_size) &&
+						     pos >= 0; pos--, blp--)
+						; /* empty */
+					if (pos < 0)
+						goto is_bop;
+				}
+			}
+			pos += 1;
+		} else if (count > 0) {
+			for (i = 0, blp = devip->tape_blocks[partition] + pos;
+			     i < count; i++, pos++, blp++) {
+				for ( ; !IS_TAPE_BLOCK_FM(blp->fl_size) &&
+					      !IS_TAPE_BLOCK_EOD(blp->fl_size) &&
+					      pos < devip->tape_eop[partition];
+				      pos++, blp++)
+					; /* empty */
+				if (IS_TAPE_BLOCK_EOD(blp->fl_size))
+					goto is_eod;
+				if (pos >= devip->tape_eop[partition])
+					goto is_eop;
+			}
+		}
+	} else if (code == 3) { /* EOD */
+		for (blp = devip->tape_blocks[partition] + pos;
+		     !IS_TAPE_BLOCK_EOD(blp->fl_size) && pos < devip->tape_eop[partition];
+		     pos++, blp++)
+			; /* empty */
+		if (pos >= devip->tape_eop[partition])
+			goto is_eop;
+	} else {
+		/* sequential filemarks not supported */
+		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 8, -1);
+		return check_condition_result;
+	}
+	devip->tape_location[partition] = pos;
+	return 0;
+
+is_fm:
+	devip->tape_location[partition] = pos;
+	mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+			FILEMARK_DETECTED_ASCQ, count - i,
+			SENSE_FLAG_FILEMARK);
+	return check_condition_result;
+
+is_eod:
+	devip->tape_location[partition] = pos;
+	mk_sense_info_tape(scp, BLANK_CHECK, NO_ADDITIONAL_SENSE,
+			EOD_DETECTED_ASCQ, count - i,
+			0);
+	return check_condition_result;
+
+is_bop:
+	devip->tape_location[partition] = 0;
+	mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+			BEGINNING_OF_P_M_DETECTED_ASCQ, count - i,
+			SENSE_FLAG_EOM);
+	devip->tape_location[partition] = 0;
+	return check_condition_result;
+
+is_eop:
+	devip->tape_location[partition] = devip->tape_eop[partition] - 1;
+	mk_sense_info_tape(scp, MEDIUM_ERROR, NO_ADDITIONAL_SENSE,
+			EOP_EOM_DETECTED_ASCQ, (unsigned int)i,
+			SENSE_FLAG_EOM);
+	return check_condition_result;
+}
+
 static int resp_rewind(struct scsi_cmnd *scp,
 		struct sdebug_dev_info *devip)
 {
@@ -4121,6 +4256,98 @@  static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
 	return ret;
 }
 
+static int resp_read_tape(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
+{
+	u32 i, num, transfer, size;
+	u8 *cmd = scp->cmnd;
+	struct scsi_data_buffer *sdb = &scp->sdb;
+	int partition = devip->tape_partition;
+	u32 pos = devip->tape_location[partition];
+	struct tape_block *blp;
+	bool fixed, sili;
+
+	if (cmd[0] != READ_6) { /* Only Read(6) supported */
+		mk_sense_invalid_opcode(scp);
+		return illegal_condition_result;
+	}
+	fixed = (cmd[1] & 0x1) != 0;
+	sili = (cmd[1] & 0x2) != 0;
+	if (fixed && sili) {
+		mk_sense_invalid_fld(scp, SDEB_IN_CDB, 1, 1);
+		return check_condition_result;
+	}
+
+	transfer = get_unaligned_be24(cmd + 2);
+	if (fixed) {
+		num = transfer;
+		size = devip->tape_blksize;
+	} else {
+		if (transfer < TAPE_MIN_BLKSIZE ||
+			transfer > TAPE_MAX_BLKSIZE) {
+			mk_sense_invalid_fld(scp, SDEB_IN_CDB, 2, -1);
+			return check_condition_result;
+		}
+		num = 1;
+		size = transfer;
+	}
+
+	for (i = 0, blp = devip->tape_blocks[partition] + pos;
+	     i < num && pos < devip->tape_eop[partition];
+	     i++, pos++, blp++) {
+		devip->tape_location[partition] = pos + 1;
+		if (IS_TAPE_BLOCK_FM(blp->fl_size)) {
+			mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+					FILEMARK_DETECTED_ASCQ, fixed ? num - i : size,
+					SENSE_FLAG_FILEMARK);
+			scsi_set_resid(scp, (num - i) * size);
+			return check_condition_result;
+		}
+		/* Assume no REW */
+		if (IS_TAPE_BLOCK_EOD(blp->fl_size)) {
+			mk_sense_info_tape(scp, BLANK_CHECK, NO_ADDITIONAL_SENSE,
+					EOD_DETECTED_ASCQ, fixed ? num - i : size,
+					0);
+			devip->tape_location[partition] = pos;
+			scsi_set_resid(scp, (num - i) * size);
+			return check_condition_result;
+		}
+		sg_zero_buffer(sdb->table.sgl, sdb->table.nents,
+			size, i * size);
+		sg_copy_buffer(sdb->table.sgl, sdb->table.nents,
+			&(blp->data), 4, i * size, false);
+		if (fixed) {
+			if (blp->fl_size != devip->tape_blksize) {
+				scsi_set_resid(scp, (num - i) * size);
+				mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+						0, num - i,
+						SENSE_FLAG_ILI);
+				return check_condition_result;
+			}
+		} else {
+			if (blp->fl_size != size) {
+				if (blp->fl_size < size)
+					scsi_set_resid(scp, size - blp->fl_size);
+				if (!sili) {
+					mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+							0, size - blp->fl_size,
+							SENSE_FLAG_ILI);
+					return check_condition_result;
+				}
+			}
+		}
+	}
+	if (pos >= devip->tape_eop[partition]) {
+		mk_sense_info_tape(scp, NO_SENSE, NO_ADDITIONAL_SENSE,
+				EOP_EOM_DETECTED_ASCQ, fixed ? num - i : size,
+				SENSE_FLAG_EOM);
+		devip->tape_location[partition] = pos - 1;
+		return check_condition_result;
+	}
+	devip->tape_location[partition] = pos;
+
+	return 0;
+}
+
 static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 {
 	bool check_prot;
@@ -4132,6 +4359,9 @@  static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 	u8 *cmd = scp->cmnd;
 	bool meta_data_locked = false;
 
+	if (sdebug_ptype == TYPE_TAPE)
+		return resp_read_tape(scp, devip);
+
 	switch (cmd[0]) {
 	case READ_16:
 		ei_lba = 0;