linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Martin K. Petersen" <martin.petersen@oracle.com>
To: linux-scsi@vger.kernel.org
Cc: "Martin K. Petersen" <martin.petersen@oracle.com>
Subject: [PATCH 09/15] scsi: scsi_debug: Improve RDPROTECT/WRPROTECT handling
Date: Tue,  8 Jun 2021 23:39:23 -0400	[thread overview]
Message-ID: <20210609033929.3815-10-martin.petersen@oracle.com> (raw)
In-Reply-To: <20210609033929.3815-1-martin.petersen@oracle.com>

It is useful for testing purposes to be able to inject errors by
writing bad protection information to media with checking disabled and
then attempting to read it back. Extend scsi_debug's PI verification
logic to give the driver feature parity with commercially available
drives. Almost all devices with PI capability support RDPROTECT and
WRPROTECT values of 0, 1, and 3.

Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
---
 drivers/scsi/scsi_debug.c | 90 +++++++++++++++++++++++++++++----------
 1 file changed, 67 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 9033ab4911ba..25112b15ab14 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3076,6 +3076,7 @@ static void dif_copy_prot(struct scsi_cmnd *scp, sector_t sector,
 static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
 			    unsigned int sectors, u32 ei_lba)
 {
+	int ret = 0;
 	unsigned int i;
 	sector_t sector;
 	struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
@@ -3083,26 +3084,33 @@ static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
 	struct t10_pi_tuple *sdt;
 
 	for (i = 0; i < sectors; i++, ei_lba++) {
-		int ret;
-
 		sector = start_sec + i;
 		sdt = dif_store(sip, sector);
 
 		if (sdt->app_tag == cpu_to_be16(0xffff))
 			continue;
 
-		ret = dif_verify(sdt, lba2fake_store(sip, sector), sector,
-				 ei_lba);
-		if (ret) {
-			dif_errors++;
-			return ret;
+		/*
+		 * Because scsi_debug acts as both initiator and
+		 * target we proceed to verify the PI even if
+		 * RDPROTECT=3. This is done so the "initiator" knows
+		 * which type of error to return. Otherwise we would
+		 * have to iterate over the PI twice.
+		 */
+		if (scp->cmnd[1] >> 5) { /* RDPROTECT */
+			ret = dif_verify(sdt, lba2fake_store(sip, sector),
+					 sector, ei_lba);
+			if (ret) {
+				dif_errors++;
+				break;
+			}
 		}
 	}
 
 	dif_copy_prot(scp, start_sec, sectors, true);
 	dix_reads++;
 
-	return 0;
+	return ret;
 }
 
 static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
@@ -3196,12 +3204,29 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 
 	/* DIX + T10 DIF */
 	if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
-		int prot_ret = prot_verify_read(scp, lba, num, ei_lba);
-
-		if (prot_ret) {
-			read_unlock(macc_lckp);
-			mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, prot_ret);
-			return illegal_condition_result;
+		switch (prot_verify_read(scp, lba, num, ei_lba)) {
+		case 1: /* Guard tag error */
+			if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
+				read_unlock(macc_lckp);
+				mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+				return check_condition_result;
+			} else if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
+				read_unlock(macc_lckp);
+				mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+				return illegal_condition_result;
+			}
+			break;
+		case 3: /* Reference tag error */
+			if (cmd[1] >> 5 != 3) { /* RDPROTECT != 3 */
+				read_unlock(macc_lckp);
+				mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
+				return check_condition_result;
+			} else if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
+				read_unlock(macc_lckp);
+				mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
+				return illegal_condition_result;
+			}
+			break;
 		}
 	}
 
@@ -3277,9 +3302,11 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
 			sdt = piter.addr + ppage_offset;
 			daddr = diter.addr + dpage_offset;
 
-			ret = dif_verify(sdt, daddr, sector, ei_lba);
-			if (ret)
-				goto out;
+			if (SCpnt->cmnd[1] >> 5 != 3) { /* WRPROTECT */
+				ret = dif_verify(sdt, daddr, sector, ei_lba);
+				if (ret)
+					goto out;
+			}
 
 			sector++;
 			ei_lba++;
@@ -3456,12 +3483,29 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
 
 	/* DIX + T10 DIF */
 	if (unlikely(sdebug_dix && scsi_prot_sg_count(scp))) {
-		int prot_ret = prot_verify_write(scp, lba, num, ei_lba);
-
-		if (prot_ret) {
-			write_unlock(macc_lckp);
-			mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, prot_ret);
-			return illegal_condition_result;
+		switch (prot_verify_write(scp, lba, num, ei_lba)) {
+		case 1: /* Guard tag error */
+			if (scp->prot_flags & SCSI_PROT_GUARD_CHECK) {
+				write_unlock(macc_lckp);
+				mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 1);
+				return illegal_condition_result;
+			} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
+				write_unlock(macc_lckp);
+				mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 1);
+				return check_condition_result;
+			}
+			break;
+		case 3: /* Reference tag error */
+			if (scp->prot_flags & SCSI_PROT_REF_CHECK) {
+				write_unlock(macc_lckp);
+				mk_sense_buffer(scp, ILLEGAL_REQUEST, 0x10, 3);
+				return illegal_condition_result;
+			} else if (scp->cmnd[1] >> 5 != 3) { /* WRPROTECT != 3 */
+				write_unlock(macc_lckp);
+				mk_sense_buffer(scp, ABORTED_COMMAND, 0x10, 3);
+				return check_condition_result;
+			}
+			break;
 		}
 	}
 
-- 
2.31.1


  parent reply	other threads:[~2021-06-09  3:39 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-09  3:39 [PATCH 00/15] Subject: Protection information and block size cleanup Martin K. Petersen
2021-06-09  3:39 ` [PATCH 01/15] scsi: core: Add scsi_prot_ref_tag() helper Martin K. Petersen
2021-06-09 19:55   ` Bart Van Assche
2021-06-14 14:33   ` Benjamin Block
2021-06-09  3:39 ` [PATCH 02/15] scsi: lpfc: Use the proper SCSI midlayer interfaces for PI Martin K. Petersen
2021-06-09  3:39 ` [PATCH 03/15] scsi: qla2xxx: " Martin K. Petersen
2021-06-17  0:15   ` Arun Easi
2021-06-09  3:39 ` [PATCH 04/15] scsi: mpt3sas: " Martin K. Petersen
2021-06-09  3:39 ` [PATCH 05/15] scsi: mpi3mr: " Martin K. Petersen
2021-06-09  3:39 ` [PATCH 06/15] scsi: zfcp: " Martin K. Petersen
2021-06-14 14:33   ` Benjamin Block
2021-06-15  2:27     ` Martin K. Petersen
2021-06-15  9:31       ` Benjamin Block
2021-06-09  3:39 ` [PATCH 07/15] scsi: isci: " Martin K. Petersen
2021-06-09  3:39 ` [PATCH 08/15] scsi: scsi_debug: Remove dump_sector() Martin K. Petersen
2021-06-09 19:55   ` Bart Van Assche
2021-06-14 22:06   ` Douglas Gilbert
2021-06-09  3:39 ` Martin K. Petersen [this message]
2021-06-14 22:07   ` [PATCH 09/15] scsi: scsi_debug: Improve RDPROTECT/WRPROTECT handling Douglas Gilbert
2021-06-09  3:39 ` [PATCH 10/15] scsi: core: Introduce scsi_get_sector() Martin K. Petersen
2021-06-14 14:48   ` Benjamin Block
2021-06-15  2:28     ` Martin K. Petersen
2021-06-15  9:33       ` Benjamin Block
2021-06-09  3:39 ` [PATCH 11/15] scsi: iser: Use scsi_get_sector() instead of scsi_get_lba() Martin K. Petersen
2021-06-09  3:39 ` [PATCH 12/15] scsi: core: Make scsi_get_lba() return the LBA Martin K. Petersen
2021-06-09 19:57   ` Bart Van Assche
2021-06-14 14:50   ` Benjamin Block
2021-06-15  9:34     ` Benjamin Block
2021-06-09  3:39 ` [PATCH 13/15] scsi: core: Add helper to return number of logical blocks in a request Martin K. Petersen
2021-06-09 19:58   ` Bart Van Assche
2021-06-10  3:19     ` Martin K. Petersen
2021-06-10  3:40       ` Bart Van Assche
2021-06-09  3:39 ` [PATCH 14/15] scsi: lpfc: Switch to scsi_get_block_count() Martin K. Petersen
2021-06-09  3:39 ` [PATCH 15/15] scsi: ufs: core: Use scsi_get_lba() to get LBA Martin K. Petersen
2021-06-09 19:59   ` Bart Van Assche
2021-07-16 21:27 ` [PATCH 00/15] Subject: Protection information and block size cleanup Bart Van Assche
2021-07-19  1:43   ` Martin K. Petersen
2021-07-21  3:53     ` Bart Van Assche
2021-07-24  2:13 ` Martin K. Petersen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210609033929.3815-10-martin.petersen@oracle.com \
    --to=martin.petersen@oracle.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).