linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support
@ 2014-03-17  5:32 Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 1/7] virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition Nicholas A. Bellinger
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Hi MST, MKP, Paolo & Co,

This is an updated -v2 series for adding T1O protection information (PI)
SGL passthrough support between virtio-scsi LLD + vhost-scsi fabric
endpoints.

The patch series is available at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git vhost-dif

Following Paolo's recommendations, this patch adds a new virtio_scsi command
header (virtio_scsi_cmd_req_pi) with the following elements to signal the
existence of protection information:

     ->do_pi_niov (DataOUT PI number of iovecs)
     ->di_pi_noiv (DataIN PI number of iovecs)

Also included is the change to attach protection information preceeding the
actual DataOUT + DataIN data payload, thus making a future improvement of
processing virtio buffers inline a possibility.

vhost-scsi code has also been updated to determine virtio_scsi_cmd_req or
virtio_scsi_cmd_req_pi usage based upon the first iovec's (header) length,
and then continues to process in either mode accordingly.

As with the original RFC, the virtio-scsi patch still contains a hack
to force DIX/DIF to be enabled, regardless of host provided feature bits.
This regression bug still needs to be tracked down.

v2 changes:
  - Add virtio_scsi_cmd_req_pi header (Paolo + nab)
  - Use virtio_scsi_cmd_req_pi instead of existing ->prio (Paolo + nab)
  - Make protection buffer come before data buffer (Paolo + nab)
  - Update vhost_scsi_get_tag() parameter usage (nab)

Please review.

Thanks!

--nab

Nicholas Bellinger (7):
  virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition
  vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl
  vhost/scsi: Add preallocation of protection SGLs
  vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic
  vhost/scsi: Enable T10 PI IOV -> SGL memory mapping
  vhost/scsi: Add new VIRTIO_SCSI_F_T10_PI feature bit
  virtio-scsi: Enable DIF/DIX modes in SCSI host LLD

 drivers/scsi/virtio_scsi.c  |   79 +++++++++---
 drivers/vhost/scsi.c        |  289 +++++++++++++++++++++++++++++--------------
 include/linux/virtio_scsi.h |   15 ++-
 3 files changed, 273 insertions(+), 110 deletions(-)

-- 
1.7.2.5


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [RFCv2 1/7] virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
@ 2014-03-17  5:32 ` Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 2/7] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl Nicholas A. Bellinger
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger, Sagi Grimberg

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch adds a virtio_scsi_cmd_req_pi header as recommened by
Paolo that contains do_pi_niov + di_pi_niov elements used for
signaling when protection information buffers are expected to
preceed the data buffers.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 include/linux/virtio_scsi.h |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
index 4195b97..4dc5998 100644
--- a/include/linux/virtio_scsi.h
+++ b/include/linux/virtio_scsi.h
@@ -35,11 +35,23 @@ struct virtio_scsi_cmd_req {
 	u8 lun[8];		/* Logical Unit Number */
 	u64 tag;		/* Command identifier */
 	u8 task_attr;		/* Task attribute */
-	u8 prio;
+	u8 prio;		/* SAM command priority field */
 	u8 crn;
 	u8 cdb[VIRTIO_SCSI_CDB_SIZE];
 } __packed;
 
+/* SCSI command request, followed by protection information */
+struct virtio_scsi_cmd_req_pi {
+	u8 lun[8];		/* Logical Unit Number */
+	u64 tag;		/* Command identifier */
+	u8 task_attr;		/* Task attribute */
+	u8 prio;		/* SAM command priority field */
+	u8 crn;
+	u16 do_pi_niov;		/* DataOUT PI Number of iovecs */
+	u16 di_pi_niov;		/* DataIN PI Number of iovecs */
+	u8 cdb[VIRTIO_SCSI_CDB_SIZE];
+} __packed;
+
 /* Response, followed by sense data and data-in */
 struct virtio_scsi_cmd_resp {
 	u32 sense_len;		/* Sense data length */
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 2/7] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 1/7] virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition Nicholas A. Bellinger
@ 2014-03-17  5:32 ` Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 3/7] vhost/scsi: Add preallocation of protection SGLs Nicholas A. Bellinger
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

Move the overflow check for sgl_count > TCM_VHOST_PREALLOC_SGLS into
vhost_scsi_map_iov_to_sgl() so that it's based on the total number
of SGLs for all IOVs, instead of single IOVs.

Also, rename TCM_VHOST_PREALLOC_PAGES -> TCM_VHOST_PREALLOC_UPAGES
to better describe pointers to user-space pages.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c |   59 +++++++++++++++++++++----------------------------
 1 files changed, 25 insertions(+), 34 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 0a025b8..8c88ce9 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -57,7 +57,7 @@
 #define TCM_VHOST_MAX_CDB_SIZE 32
 #define TCM_VHOST_DEFAULT_TAGS 256
 #define TCM_VHOST_PREALLOC_SGLS 2048
-#define TCM_VHOST_PREALLOC_PAGES 2048
+#define TCM_VHOST_PREALLOC_UPAGES 2048
 
 struct vhost_scsi_inflight {
 	/* Wait for the flush operation to finish */
@@ -762,35 +762,28 @@ vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
 		      struct scatterlist *sgl,
 		      unsigned int sgl_count,
 		      struct iovec *iov,
-		      int write)
+		      struct page **pages,
+		      bool write)
 {
 	unsigned int npages = 0, pages_nr, offset, nbytes;
 	struct scatterlist *sg = sgl;
 	void __user *ptr = iov->iov_base;
 	size_t len = iov->iov_len;
-	struct page **pages;
 	int ret, i;
 
-	if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
-		pr_err("vhost_scsi_map_to_sgl() psgl_count: %u greater than"
-		       " preallocated TCM_VHOST_PREALLOC_SGLS: %u\n",
-			sgl_count, TCM_VHOST_PREALLOC_SGLS);
-		return -ENOBUFS;
-	}
-
 	pages_nr = iov_num_pages(iov);
-	if (pages_nr > sgl_count)
+	if (pages_nr > sgl_count) {
+		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
+		       " sgl_count: %u\n", pages_nr, sgl_count);
 		return -ENOBUFS;
-
-	if (pages_nr > TCM_VHOST_PREALLOC_PAGES) {
+	}
+	if (pages_nr > TCM_VHOST_PREALLOC_UPAGES) {
 		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
-		       " preallocated TCM_VHOST_PREALLOC_PAGES: %u\n",
-			pages_nr, TCM_VHOST_PREALLOC_PAGES);
+		       " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n",
+			pages_nr, TCM_VHOST_PREALLOC_UPAGES);
 		return -ENOBUFS;
 	}
 
-	pages = tv_cmd->tvc_upages;
-
 	ret = get_user_pages_fast((unsigned long)ptr, pages_nr, write, pages);
 	/* No pages were pinned */
 	if (ret < 0)
@@ -820,33 +813,32 @@ out:
 static int
 vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 			  struct iovec *iov,
-			  unsigned int niov,
-			  int write)
+			  int niov,
+			  bool write)
 {
-	int ret;
-	unsigned int i;
-	u32 sgl_count;
-	struct scatterlist *sg;
+	struct scatterlist *sg = cmd->tvc_sgl;
+	unsigned int sgl_count = 0;
+	int ret, i;
 
-	/*
-	 * Find out how long sglist needs to be
-	 */
-	sgl_count = 0;
 	for (i = 0; i < niov; i++)
 		sgl_count += iov_num_pages(&iov[i]);
 
-	/* TODO overflow checking */
+	if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
+		pr_err("vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than"
+			" preallocated TCM_VHOST_PREALLOC_SGLS: %u\n",
+			sgl_count, TCM_VHOST_PREALLOC_SGLS);
+		return -ENOBUFS;
+	}
 
-	sg = cmd->tvc_sgl;
 	pr_debug("%s sg %p sgl_count %u\n", __func__, sg, sgl_count);
 	sg_init_table(sg, sgl_count);
-
 	cmd->tvc_sgl_count = sgl_count;
 
-	pr_debug("Mapping %u iovecs for %u pages\n", niov, sgl_count);
+	pr_debug("Mapping iovec %p for %u pages\n", &iov[0], sgl_count);
+
 	for (i = 0; i < niov; i++) {
 		ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i],
-					    write);
+					    cmd->tvc_upages, write);
 		if (ret < 0) {
 			for (i = 0; i < cmd->tvc_sgl_count; i++)
 				put_page(sg_page(&cmd->tvc_sgl[i]));
@@ -854,7 +846,6 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 			cmd->tvc_sgl_count = 0;
 			return ret;
 		}
-
 		sg += ret;
 		sgl_count -= ret;
 	}
@@ -1753,7 +1744,7 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
 		}
 
 		tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) *
-					TCM_VHOST_PREALLOC_PAGES, GFP_KERNEL);
+					TCM_VHOST_PREALLOC_UPAGES, GFP_KERNEL);
 		if (!tv_cmd->tvc_upages) {
 			mutex_unlock(&tpg->tv_tpg_mutex);
 			pr_err("Unable to allocate tv_cmd->tvc_upages\n");
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 3/7] vhost/scsi: Add preallocation of protection SGLs
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 1/7] virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 2/7] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl Nicholas A. Bellinger
@ 2014-03-17  5:32 ` Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 4/7] vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic Nicholas A. Bellinger
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch updates tcm_vhost_make_nexus() to pre-allocate per descriptor
tcm_vhost_cmd->tvc_prot_sgl[] used to expose protection SGLs from within
virtio-scsi guest memory to vhost-scsi.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c |   15 ++++++++++++++-
 1 files changed, 14 insertions(+), 1 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 8c88ce9..a2cb289 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -58,6 +58,7 @@
 #define TCM_VHOST_DEFAULT_TAGS 256
 #define TCM_VHOST_PREALLOC_SGLS 2048
 #define TCM_VHOST_PREALLOC_UPAGES 2048
+#define TCM_VHOST_PREALLOC_PROT_SGLS 512
 
 struct vhost_scsi_inflight {
 	/* Wait for the flush operation to finish */
@@ -83,6 +84,7 @@ struct tcm_vhost_cmd {
 	u32 tvc_lun;
 	/* Pointer to the SGL formatted memory from virtio-scsi */
 	struct scatterlist *tvc_sgl;
+	struct scatterlist *tvc_prot_sgl;
 	struct page **tvc_upages;
 	/* Pointer to response */
 	struct virtio_scsi_cmd_resp __user *tvc_resp;
@@ -717,7 +719,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
 	struct tcm_vhost_cmd *cmd;
 	struct tcm_vhost_nexus *tv_nexus;
 	struct se_session *se_sess;
-	struct scatterlist *sg;
+	struct scatterlist *sg, *prot_sg;
 	struct page **pages;
 	int tag;
 
@@ -736,10 +738,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
 
 	cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag];
 	sg = cmd->tvc_sgl;
+	prot_sg = cmd->tvc_prot_sgl;
 	pages = cmd->tvc_upages;
 	memset(cmd, 0, sizeof(struct tcm_vhost_cmd));
 
 	cmd->tvc_sgl = sg;
+	cmd->tvc_prot_sgl = prot_sg;
 	cmd->tvc_upages = pages;
 	cmd->tvc_se_cmd.map_tag = tag;
 	cmd->tvc_tag = v_req->tag;
@@ -1692,6 +1696,7 @@ static void tcm_vhost_free_cmd_map_res(struct tcm_vhost_nexus *nexus,
 		tv_cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[i];
 
 		kfree(tv_cmd->tvc_sgl);
+		kfree(tv_cmd->tvc_prot_sgl);
 		kfree(tv_cmd->tvc_upages);
 	}
 }
@@ -1750,6 +1755,14 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
 			pr_err("Unable to allocate tv_cmd->tvc_upages\n");
 			goto out;
 		}
+
+		tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) *
+					TCM_VHOST_PREALLOC_PROT_SGLS, GFP_KERNEL);
+		if (!tv_cmd->tvc_prot_sgl) {
+			mutex_unlock(&tpg->tv_tpg_mutex);
+			pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
+			goto out;
+		}
 	}
 	/*
 	 * Since we are running in 'demo mode' this call with generate a
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 4/7] vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
                   ` (2 preceding siblings ...)
  2014-03-17  5:32 ` [RFCv2 3/7] vhost/scsi: Add preallocation of protection SGLs Nicholas A. Bellinger
@ 2014-03-17  5:32 ` Nicholas A. Bellinger
  2014-03-17  5:32 ` [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping Nicholas A. Bellinger
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger, Sagi Grimberg

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch adds vhost_scsi_map_iov_to_prot() to perform the mapping of
T10 data integrity memory between virtio iov + struct scatterlist using
get_user_pages_fast() following existing code.

As with vhost_scsi_map_iov_to_sgl(), this does sanity checks against the
total prot_sgl_count vs. pre-allocated SGLs, and loops across protection
iovs using vhost_scsi_map_to_sgl() to perform the actual memory mapping.

Also update tcm_vhost_release_cmd() to release associated tvc_prot_sgl[]
struct page.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index a2cb289..f720709 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -80,6 +80,7 @@ struct tcm_vhost_cmd {
 	u64 tvc_tag;
 	/* The number of scatterlists associated with this cmd */
 	u32 tvc_sgl_count;
+	u32 tvc_prot_sgl_count;
 	/* Saved unpacked SCSI LUN for tcm_vhost_submission_work() */
 	u32 tvc_lun;
 	/* Pointer to the SGL formatted memory from virtio-scsi */
@@ -458,12 +459,16 @@ static void tcm_vhost_release_cmd(struct se_cmd *se_cmd)
 	struct tcm_vhost_cmd *tv_cmd = container_of(se_cmd,
 				struct tcm_vhost_cmd, tvc_se_cmd);
 	struct se_session *se_sess = se_cmd->se_sess;
+	int i;
 
 	if (tv_cmd->tvc_sgl_count) {
-		u32 i;
 		for (i = 0; i < tv_cmd->tvc_sgl_count; i++)
 			put_page(sg_page(&tv_cmd->tvc_sgl[i]));
 	}
+	if (tv_cmd->tvc_prot_sgl_count) {
+		for (i = 0; i < tv_cmd->tvc_prot_sgl_count; i++)
+			put_page(sg_page(&tv_cmd->tvc_prot_sgl[i]));
+	}
 
 	tcm_vhost_put_inflight(tv_cmd->inflight);
 	percpu_ida_free(&se_sess->sess_tag_pool, se_cmd->map_tag);
@@ -856,6 +861,47 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 	return 0;
 }
 
+static int
+vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
+			   struct iovec *iov,
+			   int niov,
+			   bool write)
+{
+	struct scatterlist *prot_sg = cmd->tvc_prot_sgl;
+	unsigned int prot_sgl_count = 0;
+	int ret, i;
+
+	for (i = 0; i < niov; i++)
+		prot_sgl_count += iov_num_pages(&iov[i]);
+
+	if (prot_sgl_count > TCM_VHOST_PREALLOC_PROT_SGLS) {
+		pr_err("vhost_scsi_map_iov_to_prot() sgl_count: %u greater than"
+			" preallocated TCM_VHOST_PREALLOC_PROT_SGLS: %u\n",
+			prot_sgl_count, TCM_VHOST_PREALLOC_PROT_SGLS);
+		return -ENOBUFS;
+	}
+
+	pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__,
+		 prot_sg, prot_sgl_count);
+	sg_init_table(prot_sg, prot_sgl_count);
+	cmd->tvc_prot_sgl_count = prot_sgl_count;
+
+	for (i = 0; i < niov; i++) {
+		ret = vhost_scsi_map_to_sgl(cmd, prot_sg, prot_sgl_count, &iov[i],
+					    cmd->tvc_upages, write);
+		if (ret < 0) {
+			for (i = 0; i < cmd->tvc_prot_sgl_count; i++)
+				put_page(sg_page(&cmd->tvc_prot_sgl[i]));
+
+			cmd->tvc_prot_sgl_count = 0;
+			return ret;
+		}
+		prot_sg += ret;
+		prot_sgl_count -= ret;
+	}
+	return 0;
+}
+
 static void tcm_vhost_submission_work(struct work_struct *work)
 {
 	struct tcm_vhost_cmd *cmd =
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
                   ` (3 preceding siblings ...)
  2014-03-17  5:32 ` [RFCv2 4/7] vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic Nicholas A. Bellinger
@ 2014-03-17  5:32 ` Nicholas A. Bellinger
  2014-03-17 11:02   ` Paolo Bonzini
  2014-03-17  5:33 ` [RFCv2 6/7] vhost/scsi: Add new VIRTIO_SCSI_F_T10_PI feature bit Nicholas A. Bellinger
  2014-03-17  5:33 ` [RFCv2 7/7] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD Nicholas A. Bellinger
  6 siblings, 1 reply; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:32 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger, Sagi Grimberg

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch updates vhost_scsi_handle_vq() to check for the existance
of virtio_scsi_cmd_req_pi comparing vq->iov[0].iov_len in order to
calculate seperate data + protection SGLs from data_num.

Also update tcm_vhost_submission_work() to pass the pre-allocated
cmd->tvc_prot_sgl[] memory into target_submit_cmd_map_sgls(), and
update vhost_scsi_get_tag() parameters to accept scsi_tag, lun, and
task_attr.

v2 changes:
  - Use virtio_scsi_cmd_req_pi instead of existing ->prio (Paolo)
  - Make protection buffer come before data buffer (Paolo)
  - Update vhost_scsi_get_tag() parameter usage

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c |  164 +++++++++++++++++++++++++++++++++----------------
 1 files changed, 110 insertions(+), 54 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index f720709..00903dc 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -715,11 +715,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
 }
 
 static struct tcm_vhost_cmd *
-vhost_scsi_get_tag(struct vhost_virtqueue *vq,
-			struct tcm_vhost_tpg *tpg,
-			struct virtio_scsi_cmd_req *v_req,
-			u32 exp_data_len,
-			int data_direction)
+vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg,
+		   unsigned char *cdb, u64 scsi_tag, u16 lun, u8 task_attr,
+		   u32 exp_data_len, int data_direction)
 {
 	struct tcm_vhost_cmd *cmd;
 	struct tcm_vhost_nexus *tv_nexus;
@@ -751,13 +749,16 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
 	cmd->tvc_prot_sgl = prot_sg;
 	cmd->tvc_upages = pages;
 	cmd->tvc_se_cmd.map_tag = tag;
-	cmd->tvc_tag = v_req->tag;
-	cmd->tvc_task_attr = v_req->task_attr;
+	cmd->tvc_tag = scsi_tag;
+	cmd->tvc_lun = lun;
+	cmd->tvc_task_attr = task_attr;
 	cmd->tvc_exp_data_len = exp_data_len;
 	cmd->tvc_data_direction = data_direction;
 	cmd->tvc_nexus = tv_nexus;
 	cmd->inflight = tcm_vhost_get_inflight(vq);
 
+	memcpy(cmd->tvc_cdb, cdb, TCM_VHOST_MAX_CDB_SIZE);
+
 	return cmd;
 }
 
@@ -908,18 +909,15 @@ static void tcm_vhost_submission_work(struct work_struct *work)
 		container_of(work, struct tcm_vhost_cmd, work);
 	struct tcm_vhost_nexus *tv_nexus;
 	struct se_cmd *se_cmd = &cmd->tvc_se_cmd;
-	struct scatterlist *sg_ptr, *sg_bidi_ptr = NULL;
-	int rc, sg_no_bidi = 0;
+	struct scatterlist *sg_ptr, *sg_prot_ptr = NULL;
+	int rc;
 
+	/* FIXME: BIDI operation */
 	if (cmd->tvc_sgl_count) {
 		sg_ptr = cmd->tvc_sgl;
-/* FIXME: Fix BIDI operation in tcm_vhost_submission_work() */
-#if 0
-		if (se_cmd->se_cmd_flags & SCF_BIDI) {
-			sg_bidi_ptr = NULL;
-			sg_no_bidi = 0;
-		}
-#endif
+
+		if (cmd->tvc_prot_sgl_count)
+			sg_prot_ptr = cmd->tvc_prot_sgl;
 	} else {
 		sg_ptr = NULL;
 	}
@@ -930,7 +928,7 @@ static void tcm_vhost_submission_work(struct work_struct *work)
 			cmd->tvc_lun, cmd->tvc_exp_data_len,
 			cmd->tvc_task_attr, cmd->tvc_data_direction,
 			TARGET_SCF_ACK_KREF, sg_ptr, cmd->tvc_sgl_count,
-			sg_bidi_ptr, sg_no_bidi, NULL, 0);
+			NULL, 0, sg_prot_ptr, cmd->tvc_prot_sgl_count);
 	if (rc < 0) {
 		transport_send_check_condition_and_sense(se_cmd,
 				TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
@@ -962,12 +960,18 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 {
 	struct tcm_vhost_tpg **vs_tpg;
 	struct virtio_scsi_cmd_req v_req;
+	struct virtio_scsi_cmd_req_pi v_req_pi;
 	struct tcm_vhost_tpg *tpg;
 	struct tcm_vhost_cmd *cmd;
-	u32 exp_data_len, data_first, data_num, data_direction;
+	u64 tag;
+	u32 exp_data_len, data_first, data_num, data_direction, prot_first;
 	unsigned out, in, i;
-	int head, ret;
-	u8 target;
+	int head, ret, data_niov, prot_niov;
+	size_t req_size;
+	u16 lun;
+	u8 *target, task_attr;
+	bool hdr_pi;
+	unsigned char *req, *cdb;
 
 	mutex_lock(&vq->mutex);
 	/*
@@ -998,7 +1002,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 			break;
 		}
 
-/* FIXME: BIDI operation */
+		/* FIXME: BIDI operation */
 		if (out == 1 && in == 1) {
 			data_direction = DMA_NONE;
 			data_first = 0;
@@ -1028,23 +1032,31 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 			break;
 		}
 
-		if (unlikely(vq->iov[0].iov_len != sizeof(v_req))) {
-			vq_err(vq, "Expecting virtio_scsi_cmd_req, got %zu"
+		if (vq->iov[0].iov_len == sizeof(v_req_pi)) {
+			req = (unsigned char *)&v_req_pi;
+			target = &v_req_pi.lun[1];
+			req_size = sizeof(v_req_pi);
+			hdr_pi = true;
+		} else if (vq->iov[0].iov_len == sizeof(v_req)) {
+			req = (unsigned char *)&v_req;
+			target = &v_req.lun[1];
+			req_size = sizeof(v_req);
+			hdr_pi = false;
+		} else {
+			vq_err(vq, "Expecting virtio_scsi_cmd_req*, got %zu"
 				" bytes\n", vq->iov[0].iov_len);
 			break;
 		}
+
 		pr_debug("Calling __copy_from_user: vq->iov[0].iov_base: %p,"
-			" len: %zu\n", vq->iov[0].iov_base, sizeof(v_req));
-		ret = __copy_from_user(&v_req, vq->iov[0].iov_base,
-				sizeof(v_req));
+			" len: %zu\n", vq->iov[0].iov_base, req_size);
+		ret = __copy_from_user(req, vq->iov[0].iov_base, req_size);
 		if (unlikely(ret)) {
 			vq_err(vq, "Faulted on virtio_scsi_cmd_req\n");
 			break;
 		}
 
-		/* Extract the tpgt */
-		target = v_req.lun[1];
-		tpg = ACCESS_ONCE(vs_tpg[target]);
+		tpg = ACCESS_ONCE(vs_tpg[*target]);
 
 		/* Target does not exist, fail the request */
 		if (unlikely(!tpg)) {
@@ -1052,17 +1064,73 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 			continue;
 		}
 
+		data_niov = data_num;
+		prot_niov = prot_first = 0;
+		/*
+		 * Determine if any proteciton information iovecs are preceeding
+		 * the actual data payload, and adjust data_niov + data_first
+		 *
+		 * Also extract virtio_scsi header bits for vhost_scsi_get_tag()
+		 */
+		if (data_num && hdr_pi) {
+			if (v_req_pi.do_pi_niov) {
+				if (data_direction != DMA_TO_DEVICE) {
+					vq_err(vq, "Received non zero do_pi_niov"
+						", but wrong data_direction\n");
+					goto err_cmd;
+				}
+				prot_niov = v_req_pi.do_pi_niov;
+			} else if (v_req_pi.di_pi_niov) {
+				if (data_direction != DMA_FROM_DEVICE) {
+					vq_err(vq, "Received non zero di_pi_niov"
+						", but wrong data_direction\n");
+					goto err_cmd;
+				}
+				prot_niov = v_req_pi.di_pi_niov;
+			} else {
+				vq_err(vq, "Received zero do_pi_niov + di_pi_niov"
+					", but still using hdr_pi\n");
+				goto err_cmd;
+			}
+
+			data_niov = data_num - prot_niov;
+			prot_first = data_first;
+			data_first += prot_niov;
+
+			tag = v_req_pi.tag;
+			task_attr = v_req_pi.task_attr;
+			cdb = &v_req_pi.cdb[0];
+			lun = ((v_req_pi.lun[2] << 8) | v_req_pi.lun[3]) & 0x3FFF;
+		} else {
+			tag = v_req.tag;
+			task_attr = v_req.task_attr;
+			cdb = &v_req.cdb[0];
+			lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF;
+		}
 		exp_data_len = 0;
-		for (i = 0; i < data_num; i++)
+		for (i = 0; i < data_niov; i++)
 			exp_data_len += vq->iov[data_first + i].iov_len;
+		/*
+		 * Check that the recieved CDB size does not exceeded our
+		 * hardcoded max for vhost-scsi
+		 *
+		 * TODO what if cdb was too small for varlen cdb header?
+		 */
+		if (unlikely(scsi_command_size(cdb) > TCM_VHOST_MAX_CDB_SIZE)) {
+			vq_err(vq, "Received SCSI CDB with command_size: %d that"
+				" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
+				scsi_command_size(cdb), TCM_VHOST_MAX_CDB_SIZE);
+			goto err_cmd;
+		}
 
-		cmd = vhost_scsi_get_tag(vq, tpg, &v_req,
+		cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr,
 					 exp_data_len, data_direction);
 		if (IS_ERR(cmd)) {
 			vq_err(vq, "vhost_scsi_get_tag failed %ld\n",
 					PTR_ERR(cmd));
 			goto err_cmd;
 		}
+
 		pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction"
 			": %d\n", cmd, exp_data_len, data_direction);
 
@@ -1070,40 +1138,28 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 		cmd->tvc_vq = vq;
 		cmd->tvc_resp = vq->iov[out].iov_base;
 
-		/*
-		 * Copy in the recieved CDB descriptor into cmd->tvc_cdb
-		 * that will be used by tcm_vhost_new_cmd_map() and down into
-		 * target_setup_cmd_from_cdb()
-		 */
-		memcpy(cmd->tvc_cdb, v_req.cdb, TCM_VHOST_MAX_CDB_SIZE);
-		/*
-		 * Check that the recieved CDB size does not exceeded our
-		 * hardcoded max for tcm_vhost
-		 */
-		/* TODO what if cdb was too small for varlen cdb header? */
-		if (unlikely(scsi_command_size(cmd->tvc_cdb) >
-					TCM_VHOST_MAX_CDB_SIZE)) {
-			vq_err(vq, "Received SCSI CDB with command_size: %d that"
-				" exceeds SCSI_MAX_VARLEN_CDB_SIZE: %d\n",
-				scsi_command_size(cmd->tvc_cdb),
-				TCM_VHOST_MAX_CDB_SIZE);
-			goto err_free;
-		}
-		cmd->tvc_lun = ((v_req.lun[2] << 8) | v_req.lun[3]) & 0x3FFF;
-
 		pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n",
 			cmd->tvc_cdb[0], cmd->tvc_lun);
 
+		if (prot_niov) {
+			ret = vhost_scsi_map_iov_to_prot(cmd,
+					&vq->iov[prot_first], prot_niov,
+					data_direction == DMA_FROM_DEVICE);
+			if (unlikely(ret)) {
+				vq_err(vq, "Failed to map iov to"
+					" prot_sgl\n");
+				goto err_free;
+			}
+		}
 		if (data_direction != DMA_NONE) {
 			ret = vhost_scsi_map_iov_to_sgl(cmd,
-					&vq->iov[data_first], data_num,
+					&vq->iov[data_first], data_niov,
 					data_direction == DMA_FROM_DEVICE);
 			if (unlikely(ret)) {
 				vq_err(vq, "Failed to map iov to sgl\n");
 				goto err_free;
 			}
 		}
-
 		/*
 		 * Save the descriptor from vhost_get_vq_desc() to be used to
 		 * complete the virtio-scsi request in TCM callback context via
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 6/7] vhost/scsi: Add new VIRTIO_SCSI_F_T10_PI feature bit
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
                   ` (4 preceding siblings ...)
  2014-03-17  5:32 ` [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping Nicholas A. Bellinger
@ 2014-03-17  5:33 ` Nicholas A. Bellinger
  2014-03-17  5:33 ` [RFCv2 7/7] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD Nicholas A. Bellinger
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:33 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger, Sagi Grimberg

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch adds a VIRTIO_SCSI_F_T10_PI feature bit for signaling
host support of accepting T10 protection information SGLs from
virtio-scsi guest.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c        |    3 ++-
 include/linux/virtio_scsi.h |    1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 00903dc..f9bbc5e6 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -169,7 +169,8 @@ enum {
 };
 
 enum {
-	VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG)
+	VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG) |
+					       (1ULL << VIRTIO_SCSI_F_T10_PI)
 };
 
 #define VHOST_SCSI_MAX_TARGET	256
diff --git a/include/linux/virtio_scsi.h b/include/linux/virtio_scsi.h
index 4dc5998..e674b2b 100644
--- a/include/linux/virtio_scsi.h
+++ b/include/linux/virtio_scsi.h
@@ -109,6 +109,7 @@ struct virtio_scsi_config {
 #define VIRTIO_SCSI_F_INOUT                    0
 #define VIRTIO_SCSI_F_HOTPLUG                  1
 #define VIRTIO_SCSI_F_CHANGE                   2
+#define VIRTIO_SCSI_F_T10_PI                   3
 
 /* Response codes */
 #define VIRTIO_SCSI_S_OK                       0
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [RFCv2 7/7] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD
  2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
                   ` (5 preceding siblings ...)
  2014-03-17  5:33 ` [RFCv2 6/7] vhost/scsi: Add new VIRTIO_SCSI_F_T10_PI feature bit Nicholas A. Bellinger
@ 2014-03-17  5:33 ` Nicholas A. Bellinger
  6 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17  5:33 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Paolo Bonzini, Martin K. Petersen, Christoph Hellwig,
	Hannes Reinecke, Sagi Grimberg, H. Peter Anvin,
	Nicholas Bellinger, Sagi Grimberg

From: Nicholas Bellinger <nab@linux-iscsi.org>

This patch updates virtscsi_probe() to setup necessary Scsi_Host
level protection resources. (currently hardcoded to 1)

It changes virtscsi_add_cmd() to attach outgoing / incoming
protection SGLs preceeding the data payload, and is using the
new virtio_scsi_cmd_req_pi->d[oi],pi_niv field to signal
to signal to vhost/scsi how many prot_sgs to expect.

v2 changes:
  - Make protection buffer come before data buffer (Paolo)
  - Enable virtio_scsi_cmd_req_pi usage (Paolo)

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: Sagi Grimberg <sagig@dev.mellanox.co.il>
Cc: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/scsi/virtio_scsi.c |   79 ++++++++++++++++++++++++++++++++++----------
 1 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 16bfd50..4cccfed 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -37,6 +37,7 @@ struct virtio_scsi_cmd {
 	struct completion *comp;
 	union {
 		struct virtio_scsi_cmd_req       cmd;
+		struct virtio_scsi_cmd_req_pi    cmd_pi;
 		struct virtio_scsi_ctrl_tmf_req  tmf;
 		struct virtio_scsi_ctrl_an_req   an;
 	} req;
@@ -440,7 +441,7 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
 			    size_t req_size, size_t resp_size, gfp_t gfp)
 {
 	struct scsi_cmnd *sc = cmd->sc;
-	struct scatterlist *sgs[4], req, resp;
+	struct scatterlist *sgs[6], req, resp;
 	struct sg_table *out, *in;
 	unsigned out_num = 0, in_num = 0;
 
@@ -458,16 +459,24 @@ static int virtscsi_add_cmd(struct virtqueue *vq,
 	sgs[out_num++] = &req;
 
 	/* Data-out buffer.  */
-	if (out)
+	if (out) {
+		/* Place WRITE protection SGLs before Data OUT payload */
+		if (scsi_prot_sg_count(sc))
+			sgs[out_num++] = scsi_prot_sglist(sc);
 		sgs[out_num++] = out->sgl;
+	}
 
 	/* Response header.  */
 	sg_init_one(&resp, &cmd->resp, resp_size);
 	sgs[out_num + in_num++] = &resp;
 
 	/* Data-in buffer */
-	if (in)
+	if (in) {
+		/* Place READ protection SGLs before Data IN payload */
+		if (scsi_prot_sg_count(sc))
+			sgs[out_num + in_num++] = scsi_prot_sglist(sc);
 		sgs[out_num + in_num++] = in->sgl;
+	}
 
 	return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp);
 }
@@ -492,12 +501,36 @@ static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq,
 	return err;
 }
 
+static void virtio_scsi_init_hdr(struct virtio_scsi_cmd_req *cmd,
+				 struct scsi_cmnd *sc)
+{
+	cmd->lun[0] = 1;
+	cmd->lun[1] = sc->device->id;
+	cmd->lun[2] = (sc->device->lun >> 8) | 0x40;
+	cmd->lun[3] = sc->device->lun & 0xff;
+	cmd->tag = (unsigned long)sc;
+	cmd->task_attr = VIRTIO_SCSI_S_SIMPLE;
+	cmd->prio = 0;
+	cmd->crn = 0;
+}
+
+static void virtio_scsi_init_hdr_pi(struct virtio_scsi_cmd_req_pi *cmd_pi,
+				    struct scsi_cmnd *sc)
+{
+	virtio_scsi_init_hdr((struct virtio_scsi_cmd_req *)cmd_pi, sc);
+
+	if (sc->sc_data_direction == DMA_TO_DEVICE)
+		cmd_pi->do_pi_niov = scsi_prot_sg_count(sc);
+	else if (sc->sc_data_direction == DMA_FROM_DEVICE)
+		cmd_pi->di_pi_niov = scsi_prot_sg_count(sc);
+}
+
 static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
 				 struct virtio_scsi_vq *req_vq,
 				 struct scsi_cmnd *sc)
 {
 	struct virtio_scsi_cmd *cmd;
-	int ret;
+	int ret, req_size;
 
 	struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
 	BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
@@ -515,22 +548,20 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi,
 
 	memset(cmd, 0, sizeof(*cmd));
 	cmd->sc = sc;
-	cmd->req.cmd = (struct virtio_scsi_cmd_req){
-		.lun[0] = 1,
-		.lun[1] = sc->device->id,
-		.lun[2] = (sc->device->lun >> 8) | 0x40,
-		.lun[3] = sc->device->lun & 0xff,
-		.tag = (unsigned long)sc,
-		.task_attr = VIRTIO_SCSI_S_SIMPLE,
-		.prio = 0,
-		.crn = 0,
-	};
 
 	BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE);
-	memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
 
-	if (virtscsi_kick_cmd(req_vq, cmd,
-			      sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
+	if (scsi_prot_sg_count(sc)) {
+		virtio_scsi_init_hdr_pi(&cmd->req.cmd_pi, sc);
+		memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len);
+		req_size = sizeof(cmd->req.cmd_pi);
+	} else {
+		virtio_scsi_init_hdr(&cmd->req.cmd, sc);
+		memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len);
+		req_size = sizeof(cmd->req.cmd);
+	}
+
+	if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd),
 			      GFP_ATOMIC) == 0)
 		ret = 0;
 	else
@@ -871,7 +902,7 @@ static int virtscsi_probe(struct virtio_device *vdev)
 {
 	struct Scsi_Host *shost;
 	struct virtio_scsi *vscsi;
-	int err;
+	int err, host_prot;
 	u32 sg_elems, num_targets;
 	u32 cmd_per_lun;
 	u32 num_queues;
@@ -921,6 +952,17 @@ static int virtscsi_probe(struct virtio_device *vdev)
 	shost->max_id = num_targets;
 	shost->max_channel = 0;
 	shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE;
+
+	/* FIXME: Figure out why this is broken.. */
+	if (1 || virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) {
+		host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
+			    SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION |
+			    SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION;
+
+		scsi_host_set_prot(shost, host_prot);
+		scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+	}
+
 	err = scsi_add_host(shost, &vdev->dev);
 	if (err)
 		goto scsi_add_host_failed;
@@ -990,6 +1032,7 @@ static struct virtio_device_id id_table[] = {
 static unsigned int features[] = {
 	VIRTIO_SCSI_F_HOTPLUG,
 	VIRTIO_SCSI_F_CHANGE,
+	VIRTIO_SCSI_F_T10_PI,
 };
 
 static struct virtio_driver virtio_scsi_driver = {
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping
  2014-03-17  5:32 ` [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping Nicholas A. Bellinger
@ 2014-03-17 11:02   ` Paolo Bonzini
  2014-03-17 19:18     ` Nicholas A. Bellinger
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2014-03-17 11:02 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, linux-kernel, kvm-devel, Michael S. Tsirkin,
	Martin K. Petersen, Christoph Hellwig, Hannes Reinecke,
	Sagi Grimberg, H. Peter Anvin, Nicholas Bellinger, Sagi Grimberg

Il 17/03/2014 06:32, Nicholas A. Bellinger ha scritto:
> +		if (vq->iov[0].iov_len == sizeof(v_req_pi)) {
> +			req = (unsigned char *)&v_req_pi;
> +			target = &v_req_pi.lun[1];
> +			req_size = sizeof(v_req_pi);
> +			hdr_pi = true;
> +		} else if (vq->iov[0].iov_len == sizeof(v_req)) {
> +			req = (unsigned char *)&v_req;
> +			target = &v_req.lun[1];
> +			req_size = sizeof(v_req);
> +			hdr_pi = false;

The right check here is on the negotiated features.

You need a matching QEMU patch to enable the protection information
feature, like this (untested):

diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
index 3983a5b..4c8d5cd 100644
--- a/hw/scsi/vhost-scsi.c
+++ b/hw/scsi/vhost-scsi.c
@@ -154,6 +154,9 @@ static uint32_t vhost_scsi_get_features(VirtIODevice *vdev,
     if (!(s->dev.features & (1 << VIRTIO_SCSI_F_HOTPLUG))) {
         features &= ~(1 << VIRTIO_SCSI_F_HOTPLUG);
     }
+    if (!(s->dev.features & (1 << VIRTIO_SCSI_F_T10_PI))) {
+        features &= ~(1 << VIRTIO_SCSI_F_T10_PI);
+    }
 
     return features;
 }
diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
index 6610b3a..4a551e9 100644
--- a/hw/scsi/virtio-scsi.c
+++ b/hw/scsi/virtio-scsi.c
@@ -629,6 +629,9 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    /* Protection information is not supported yet.  */
+    dev->guest_features &= ~VIRTIO_SCSI_F_T10_PI;
+
     scsi_bus_new(&s->bus, sizeof(s->bus), dev,
                  &virtio_scsi_scsi_info, vdev->bus_name);
 
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 9010246..8621fbf 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -267,6 +267,16 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
             .value    = "no",\
         },\
         {\
+            .driver   = "virtio-scsi-pci",\
+            .property = "prot_info",\
+            .value    = "off",\
+        },\
+        {\
+            .driver   = "vhost-scsi-pci",\
+            .property = "prot_info",\
+            .value    = "off",\
+        },\
+        {\
             .driver   = "PIIX4_PM",\
             .property = "acpi-pci-hotplug-with-bridge-support",\
             .value    = "off",\
diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
index 42b1024..a555f49 100644
--- a/include/hw/virtio/virtio-scsi.h
+++ b/include/hw/virtio/virtio-scsi.h
@@ -34,6 +34,7 @@
 #define VIRTIO_SCSI_F_INOUT                    0
 #define VIRTIO_SCSI_F_HOTPLUG                  1
 #define VIRTIO_SCSI_F_CHANGE                   2
+#define VIRTIO_SCSI_F_T10_PI                   3
 
 #define VIRTIO_SCSI_VQ_SIZE     128
 #define VIRTIO_SCSI_CDB_SIZE    32
@@ -184,7 +185,9 @@ typedef struct {
     DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG,  \
                                                        true),                  \
     DEFINE_PROP_BIT("param_change", _state, _feature_field,                    \
-                                            VIRTIO_SCSI_F_CHANGE, true)
+                                            VIRTIO_SCSI_F_CHANGE, true)        \
+    DEFINE_PROP_BIT("prot_info", _state, _feature_field,                       \
+                                            VIRTIO_SCSI_F_T10_PI, true)
 
 void virtio_scsi_common_realize(DeviceState *dev, Error **errp);
 void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp);


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping
  2014-03-17 11:02   ` Paolo Bonzini
@ 2014-03-17 19:18     ` Nicholas A. Bellinger
  0 siblings, 0 replies; 10+ messages in thread
From: Nicholas A. Bellinger @ 2014-03-17 19:18 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi, linux-kernel,
	kvm-devel, Michael S. Tsirkin, Martin K. Petersen,
	Christoph Hellwig, Hannes Reinecke, Sagi Grimberg,
	H. Peter Anvin, Sagi Grimberg

On Mon, 2014-03-17 at 12:02 +0100, Paolo Bonzini wrote:
> Il 17/03/2014 06:32, Nicholas A. Bellinger ha scritto:
> > +		if (vq->iov[0].iov_len == sizeof(v_req_pi)) {
> > +			req = (unsigned char *)&v_req_pi;
> > +			target = &v_req_pi.lun[1];
> > +			req_size = sizeof(v_req_pi);
> > +			hdr_pi = true;
> > +		} else if (vq->iov[0].iov_len == sizeof(v_req)) {
> > +			req = (unsigned char *)&v_req;
> > +			target = &v_req.lun[1];
> > +			req_size = sizeof(v_req);
> > +			hdr_pi = false;
> 
> The right check here is on the negotiated features.
> 

Mmmm, so this had been making the assumption that the PI enabled header
would only be used when the CDB itself had an associated PI SGL.

I agree it's cleaner to always use the PI enabled header when the
feature bit has been negotiated.  Fixing this up for -v3.

> You need a matching QEMU patch to enable the protection information
> feature, like this (untested):
> 

<nod>

Thanks Paolo!

--nab

> diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c
> index 3983a5b..4c8d5cd 100644
> --- a/hw/scsi/vhost-scsi.c
> +++ b/hw/scsi/vhost-scsi.c
> @@ -154,6 +154,9 @@ static uint32_t vhost_scsi_get_features(VirtIODevice *vdev,
>      if (!(s->dev.features & (1 << VIRTIO_SCSI_F_HOTPLUG))) {
>          features &= ~(1 << VIRTIO_SCSI_F_HOTPLUG);
>      }
> +    if (!(s->dev.features & (1 << VIRTIO_SCSI_F_T10_PI))) {
> +        features &= ~(1 << VIRTIO_SCSI_F_T10_PI);
> +    }
>  
>      return features;
>  }
> diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c
> index 6610b3a..4a551e9 100644
> --- a/hw/scsi/virtio-scsi.c
> +++ b/hw/scsi/virtio-scsi.c
> @@ -629,6 +629,9 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
>          return;
>      }
>  
> +    /* Protection information is not supported yet.  */
> +    dev->guest_features &= ~VIRTIO_SCSI_F_T10_PI;
> +
>      scsi_bus_new(&s->bus, sizeof(s->bus), dev,
>                   &virtio_scsi_scsi_info, vdev->bus_name);
>  
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 9010246..8621fbf 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -267,6 +267,16 @@ int e820_add_entry(uint64_t, uint64_t, uint32_t);
>              .value    = "no",\
>          },\
>          {\
> +            .driver   = "virtio-scsi-pci",\
> +            .property = "prot_info",\
> +            .value    = "off",\
> +        },\
> +        {\
> +            .driver   = "vhost-scsi-pci",\
> +            .property = "prot_info",\
> +            .value    = "off",\
> +        },\
> +        {\
>              .driver   = "PIIX4_PM",\
>              .property = "acpi-pci-hotplug-with-bridge-support",\
>              .value    = "off",\
> diff --git a/include/hw/virtio/virtio-scsi.h b/include/hw/virtio/virtio-scsi.h
> index 42b1024..a555f49 100644
> --- a/include/hw/virtio/virtio-scsi.h
> +++ b/include/hw/virtio/virtio-scsi.h
> @@ -34,6 +34,7 @@
>  #define VIRTIO_SCSI_F_INOUT                    0
>  #define VIRTIO_SCSI_F_HOTPLUG                  1
>  #define VIRTIO_SCSI_F_CHANGE                   2
> +#define VIRTIO_SCSI_F_T10_PI                   3
>  
>  #define VIRTIO_SCSI_VQ_SIZE     128
>  #define VIRTIO_SCSI_CDB_SIZE    32
> @@ -184,7 +185,9 @@ typedef struct {
>      DEFINE_PROP_BIT("hotplug", _state, _feature_field, VIRTIO_SCSI_F_HOTPLUG,  \
>                                                         true),                  \
>      DEFINE_PROP_BIT("param_change", _state, _feature_field,                    \
> -                                            VIRTIO_SCSI_F_CHANGE, true)
> +                                            VIRTIO_SCSI_F_CHANGE, true)        \
> +    DEFINE_PROP_BIT("prot_info", _state, _feature_field,                       \
> +                                            VIRTIO_SCSI_F_T10_PI, true)
>  
>  void virtio_scsi_common_realize(DeviceState *dev, Error **errp);
>  void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp);
> 



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2014-03-17 19:19 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-17  5:32 [RFCv2 0/7] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
2014-03-17  5:32 ` [RFCv2 1/7] virtio-scsi.h: Add virtio_scsi_cmd_req_pi header definition Nicholas A. Bellinger
2014-03-17  5:32 ` [RFCv2 2/7] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl Nicholas A. Bellinger
2014-03-17  5:32 ` [RFCv2 3/7] vhost/scsi: Add preallocation of protection SGLs Nicholas A. Bellinger
2014-03-17  5:32 ` [RFCv2 4/7] vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic Nicholas A. Bellinger
2014-03-17  5:32 ` [RFCv2 5/7] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping Nicholas A. Bellinger
2014-03-17 11:02   ` Paolo Bonzini
2014-03-17 19:18     ` Nicholas A. Bellinger
2014-03-17  5:33 ` [RFCv2 6/7] vhost/scsi: Add new VIRTIO_SCSI_F_T10_PI feature bit Nicholas A. Bellinger
2014-03-17  5:33 ` [RFCv2 7/7] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD Nicholas A. Bellinger

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).