scsi: scsi_debug: Split resp_write_dt0()

Prepare for enabling lock context analysis by eliminating conditional
locking.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/ef20891477dd7eac3874945660caec278893a619.1791924924.git.bvanassche@acm.org
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>
This commit is contained in:
Bart Van Assche 2026-10-13 15:10:06 -07:00 committed by Martin K. Petersen (Oracle)
parent 06c3166f25
commit 6544f731e4

View File

@ -5094,6 +5094,85 @@ static int corrupt_lbas(struct sdebug_dev_info *devip, u64 lba, u32 num,
return error;
}
/*
* Returns 0 upon success or -1 with *scsi_status set to a SCSI status code upon
* failure.
*/
static int __resp_write_dt0_dix(struct scsi_cmnd *scp,
u64 lba, u32 num,
u32 ei_lba, int *scsi_status)
{
switch (prot_verify_write(scp, lba, num, ei_lba)) {
case 1: /* Guard tag error */
if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
mk_sense_buffer(scp, ILLEGAL_REQUEST,
LOGICAL_BLOCK_GUARD_CHECK_FAILED);
*scsi_status = illegal_condition_result;
return -1;
}
if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
mk_sense_buffer(scp, ABORTED_COMMAND,
LOGICAL_BLOCK_GUARD_CHECK_FAILED);
*scsi_status = check_condition_result;
return -1;
}
break;
case 3: /* Reference tag error */
if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
mk_sense_buffer(scp, ILLEGAL_REQUEST,
LOGICAL_BLOCK_REFERENCE_TAG_CHECK_FAILED);
*scsi_status = illegal_condition_result;
return -1;
}
if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
mk_sense_buffer(scp, ABORTED_COMMAND,
LOGICAL_BLOCK_REFERENCE_TAG_CHECK_FAILED);
*scsi_status = check_condition_result;
return -1;
}
break;
}
return 0;
}
/*
* Returns the number of bytes transferred, or -1 with *scsi_status set to a
* SCSI status code on failure.
*/
static int __resp_write_dt0(struct scsi_cmnd *scp,
struct sdebug_dev_info *devip,
struct sdeb_store_info *sip, u64 lba, u32 num,
u32 ei_lba, u8 group, bool lbp, int *scsi_status)
{
int ret;
*scsi_status = check_device_access_params(scp, lba, num, true);
if (*scsi_status)
return -1;
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
ret = __resp_write_dt0_dix(scp, lba, num, ei_lba,
scsi_status);
if (ret < 0)
return ret;
}
ret = do_device_access(sip, scp, 0, lba, num, group, true, false);
if (ret < 0)
*scsi_status = DID_ERROR << 16;
if (unlikely(lbp))
map_region(sip, lba, num);
/* If ZBC zone then bump its write pointer */
if (sdebug_dev_is_zoned(devip) && ret > 0)
zbc_inc_wp(devip, lba, ret >> ilog2(sdebug_sector_size));
return ret;
}
static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
{
bool check_prot;
@ -5104,7 +5183,7 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
u64 lba;
struct sdeb_store_info *sip = devip2sip(devip, true);
u8 *cmd = scp->cmnd;
bool meta_data_locked = false;
int scsi_status = DID_ERROR << 16;
bool lbp = scsi_debug_lbp();
if (unlikely(sdebug_opts & SDEBUG_OPT_UNALIGNED_WRITE &&
@ -5174,60 +5253,16 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
if (sdebug_dev_is_zoned(devip) ||
(sdebug_dix && scsi_prot_sg_count(scp)) || lbp) {
sdeb_meta_write_lock(sip);
meta_data_locked = true;
}
ret = check_device_access_params(scp, lba, num, true);
if (ret) {
if (meta_data_locked)
sdeb_meta_write_unlock(sip);
return ret;
}
/* DIX + T10 DIF */
if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
switch (prot_verify_write(scp, lba, num, ei_lba)) {
case 1: /* Guard tag error */
if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST,
LOGICAL_BLOCK_GUARD_CHECK_FAILED);
return illegal_condition_result;
} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND,
LOGICAL_BLOCK_GUARD_CHECK_FAILED);
return check_condition_result;
}
break;
case 3: /* Reference tag error */
if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ILLEGAL_REQUEST,
LOGICAL_BLOCK_REFERENCE_TAG_CHECK_FAILED);
return illegal_condition_result;
} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
sdeb_meta_write_unlock(sip);
mk_sense_buffer(scp, ABORTED_COMMAND,
LOGICAL_BLOCK_REFERENCE_TAG_CHECK_FAILED);
return check_condition_result;
}
break;
}
}
ret = do_device_access(sip, scp, 0, lba, num, group, true, false);
if (unlikely(lbp))
map_region(sip, lba, num);
/* If ZBC zone then bump its write pointer over the data written */
if (sdebug_dev_is_zoned(devip) && ret > 0)
zbc_inc_wp(devip, lba, ret >> ilog2(sdebug_sector_size));
if (meta_data_locked)
ret = __resp_write_dt0(scp, devip, sip, lba, num, ei_lba, group,
lbp, &scsi_status);
sdeb_meta_write_unlock(sip);
} else {
ret = __resp_write_dt0(scp, devip, sip, lba, num, ei_lba, group,
lbp, &scsi_status);
}
if (unlikely(-1 == ret))
return DID_ERROR << 16;
return scsi_status;
else if (unlikely(sdebug_verbose &&
(ret < (num * sdebug_sector_size))))
sdev_printk(KERN_INFO, scp->device,