[PATCH 6 of 7] scsi: Support devices with protection information (DIF)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



5 files changed, 90 insertions(+)
drivers/scsi/Kconfig       |   15 +++++++++++++++
drivers/scsi/scsi_lib.c    |   42 ++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/scsi_scan.c   |    3 +++
include/scsi/scsi_cmnd.h   |   29 +++++++++++++++++++++++++++++
include/scsi/scsi_device.h |    1 +


 - Add support for an extra scatter-gather list containing protection
   information.

 - Remember devices with protection information turned on in INQUIRY.

Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>

---

diff -r 5be7c534c954 -r ad65bfde4e05 drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Sat Jun 07 00:45:15 2008 -0400
+++ b/drivers/scsi/Kconfig	Sat Jun 07 00:45:15 2008 -0400
@@ -260,6 +260,21 @@
 	default m
 	depends on SCSI
 	depends on MODULES
+
+config SCSI_PROTECTION
+       bool "SCSI Data Integrity Protection"
+       depends on SCSI
+       depends on BLK_DEV_INTEGRITY
+       help 
+	 Some SCSI devices support data protection features above and
+	 beyond those implemented in the transport.  Select this
+	 option to enable protection information to be transferred to
+	 and from a device.  Specifically, this option will enable DIF
+	 (Data Integrity Field) for SCSI disks.
+
+	 The SCSI protection features depend on the block layer data
+	 integrity infrastructure so the latter must be enabled for
+	 this option to work.
 
 menu "SCSI Transports"
 	depends on SCSI
diff -r 5be7c534c954 -r ad65bfde4e05 drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	Sat Jun 07 00:45:15 2008 -0400
+++ b/drivers/scsi/scsi_lib.c	Sat Jun 07 00:45:15 2008 -0400
@@ -778,6 +778,13 @@
 		kmem_cache_free(scsi_sdb_cache, bidi_sdb);
 		cmd->request->next_rq->special = NULL;
 	}
+
+#if defined(CONFIG_SCSI_PROTECTION)
+	if (scsi_prot_sg_count(cmd)) {
+		scsi_free_sgtable(cmd->prot_sdb);
+		kmem_cache_free(scsi_sdb_cache, cmd->prot_sdb);
+	}
+#endif
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
@@ -1031,6 +1038,32 @@
 	return BLKPREP_OK;
 }
 
+#if defined(CONFIG_SCSI_PROTECTION)
+static int scsi_protect_io(struct scsi_cmnd *cmd, gfp_t gfp_mask)
+{
+	struct request *req = cmd->request;
+	struct scsi_data_buffer *pdb;
+	int ivecs, count;
+
+	pdb = kmem_cache_zalloc(scsi_sdb_cache, gfp_mask);
+	if (unlikely(pdb == NULL))
+		return BLKPREP_DEFER;
+
+	ivecs = blk_rq_count_integrity_sg(req);
+
+	if (unlikely(scsi_alloc_sgtable(pdb, ivecs, gfp_mask)))
+		return BLKPREP_DEFER;
+
+	count = blk_rq_map_integrity_sg(req, pdb->table.sgl);
+	BUG_ON(unlikely(count > ivecs));
+
+	cmd->prot_sdb = pdb;
+	cmd->prot_sdb->table.nents = count;
+
+	return BLKPREP_OK;
+}
+#endif
+
 /*
  * Function:    scsi_init_io()
  *
@@ -1062,6 +1095,15 @@
 		if (error)
 			goto err_exit;
 	}
+
+#if defined(CONFIG_SCSI_PROTECTION)
+	if (blk_integrity_rq(cmd->request)) {
+		error = scsi_protect_io(cmd, gfp_mask);
+
+		if (error != BLKPREP_OK)
+			goto err_exit;
+	}
+#endif
 
 	return BLKPREP_OK ;
 
diff -r 5be7c534c954 -r ad65bfde4e05 drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Sat Jun 07 00:45:15 2008 -0400
+++ b/drivers/scsi/scsi_scan.c	Sat Jun 07 00:45:15 2008 -0400
@@ -882,6 +882,9 @@
 
 	if (*bflags & BLIST_USE_10_BYTE_MS)
 		sdev->use_10_for_ms = 1;
+
+	if (inq_result[5] & 0x1)
+		sdev->protection = 1;
 
 	/* set the device running here so that slave configure
 	 * may do I/O */
diff -r 5be7c534c954 -r ad65bfde4e05 include/scsi/scsi_cmnd.h
--- a/include/scsi/scsi_cmnd.h	Sat Jun 07 00:45:15 2008 -0400
+++ b/include/scsi/scsi_cmnd.h	Sat Jun 07 00:45:15 2008 -0400
@@ -88,6 +88,9 @@
 
 	/* These elements define the operation we ultimately want to perform */
 	struct scsi_data_buffer sdb;
+#if defined(CONFIG_SCSI_PROTECTION)
+	struct scsi_data_buffer *prot_sdb;
+#endif
 	unsigned underflow;	/* Return error if less than
 				   this amount is transferred */
 
@@ -209,4 +212,30 @@
 				 buf, buflen);
 }
 
+#if defined(CONFIG_SCSI_PROTECTION)
+
+static inline unsigned scsi_prot_sg_count(struct scsi_cmnd *cmd)
+{
+	return cmd->prot_sdb ? cmd->prot_sdb->table.nents : 0;
+}
+
+static inline struct scatterlist *scsi_prot_sglist(struct scsi_cmnd *cmd)
+{
+	return cmd->prot_sdb ? cmd->prot_sdb->table.sgl : NULL;
+}
+
+static inline struct scsi_data_buffer *scsi_prot(struct scsi_cmnd *cmd)
+{
+	return cmd->prot_sdb;
+}
+
+#define scsi_for_each_prot_sg(cmd, sg, nseg, __i)		\
+	for_each_sg(scsi_prot_sglist(cmd), sg, nseg, __i)
+
+#else /* CONFIG_SCSI_PROTECTION */
+
+#define scsi_prot_sg_count(a)		(0)
+
+#endif /* CONFIG_SCSI_PROTECTION */
+
 #endif /* _SCSI_SCSI_CMND_H */
diff -r 5be7c534c954 -r ad65bfde4e05 include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	Sat Jun 07 00:45:15 2008 -0400
+++ b/include/scsi/scsi_device.h	Sat Jun 07 00:45:15 2008 -0400
@@ -140,6 +140,7 @@
 	unsigned guess_capacity:1;	/* READ_CAPACITY might be too high by 1 */
 	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
 	unsigned last_sector_bug:1;	/* Always read last sector in a 1 sector read */
+	unsigned protection:1;		/* Data Integrity Field */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
 	struct list_head event_list;	/* asserted events */


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux