All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support
@ 2015-01-30  8:12 Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function Nicholas A. Bellinger
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

Hi MST & Paolo,

The series adds initial vhost/scsi ANY_LAYOUT layout support.

It assumes request/CDB and response/sense_buffer headers may span more
than a single iovec using lib/iovec.c logic, along with a new addition
of memcpy_fromiovec_out() to return the current re-calcuated **iov_out.

This is currently done using a new vhost_scsi_handle_vqal() callback,
and doesn't modify behavior of existing !ANY_LAYOUT code.

It also allows virtio-scsi headers + T10_PI + Data SGL payloads to span
the same iovec when pinning user-space memory via get_user_pages_fast()
code.  (Not tested yet)

So far it's functioning against v3.19-rc1 virtio-scsi LLD code, with
a layout of header -> T10_PI -> Data SGL payload in seperate iovecs
and VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 guest feature bits.

Please review.

Thank you,

--nab

Nicholas Bellinger (8):
  lib/iovec: Add memcpy_fromiovec_out library function
  vhost/scsi: Convert completion path to use memcpy_toiovecend
  vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures
  vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len
  vhost/scsi: Add common vhost_scsi_queue_desc code
  vhost/scsi: Add ANY_LAYOUT prerequisites
  vhost/scsi: Add ANY_LAYOUT support
  vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits

 drivers/vhost/scsi.c | 512 ++++++++++++++++++++++++++++++++++++++++++++-------
 include/linux/uio.h  |   2 +
 lib/iovec.c          |  27 +++
 3 files changed, 476 insertions(+), 65 deletions(-)

-- 
1.9.1

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

* [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  9:33   ` Paolo Bonzini
  2015-01-30  8:12 ` [PATCH 2/8] vhost/scsi: Convert completion path to use memcpy_toiovecend Nicholas A. Bellinger
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

This patch adds a new memcpy_fromiovec_out() library function which modifies
the passed *iov following memcpy_fromiovec(), but also returns the next current
iovec pointer via **iov_out.

This is useful for vhost ANY_LAYOUT support when guests are allowed to generate
incoming virtio request headers combined with subsequent SGL payloads into a
single iovec.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 include/linux/uio.h |  2 ++
 lib/iovec.c         | 27 +++++++++++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/linux/uio.h b/include/linux/uio.h
index 1c5e453..3e4473d 100644
--- a/include/linux/uio.h
+++ b/include/linux/uio.h
@@ -136,6 +136,8 @@ size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_
 size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
 
 int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
+			 struct iovec **iov_out, int len);
 int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
 			int offset, int len);
 int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
diff --git a/lib/iovec.c b/lib/iovec.c
index 2d99cb4..6a813dd 100644
--- a/lib/iovec.c
+++ b/lib/iovec.c
@@ -28,6 +28,33 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
 EXPORT_SYMBOL(memcpy_fromiovec);
 
 /*
+ *	Copy iovec to kernel, saving the current iov to *iov_out.
+ *	Returns -EFAULT on error.
+ */
+
+int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
+			 struct iovec **iov_out, int len)
+{
+	while (len > 0) {
+		if (iov->iov_len) {
+			int copy = min_t(unsigned int, len, iov->iov_len);
+			if (copy_from_user(kdata, iov->iov_base, copy))
+				return -EFAULT;
+			len -= copy;
+			kdata += copy;
+			iov->iov_base += copy;
+			iov->iov_len -= copy;
+		}
+		if (!iov->iov_len)
+			iov++;
+	}
+	*iov_out = iov;
+
+	return 0;
+}
+EXPORT_SYMBOL(memcpy_fromiovec_out);
+
+/*
  *	Copy kernel to iovec. Returns -EFAULT on error.
  */
 
-- 
1.9.1


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

* [PATCH 2/8] vhost/scsi: Convert completion path to use memcpy_toiovecend
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 3/8] vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures Nicholas A. Bellinger
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

Required for ANY_LAYOUT support when the incoming virtio-scsi response
header + fixed size sense buffer payload may span more than a single
iovec entry.

This changes existing code to save cmd->tvc_resp_iod instead of the
first single iovec base pointer from &vq->iov[out].

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 01c01cb..a03ac41 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -87,8 +87,8 @@ struct tcm_vhost_cmd {
 	struct scatterlist *tvc_sgl;
 	struct scatterlist *tvc_prot_sgl;
 	struct page **tvc_upages;
-	/* Pointer to response */
-	struct virtio_scsi_cmd_resp __user *tvc_resp;
+	/* Pointer to response header iovec */
+	struct iovec *tvc_resp_iov;
 	/* Pointer to vhost_scsi for our device */
 	struct vhost_scsi *tvc_vhost;
 	/* Pointer to vhost_virtqueue for the cmd */
@@ -703,7 +703,8 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
 						 se_cmd->scsi_sense_length);
 		memcpy(v_rsp.sense, cmd->tvc_sense_buf,
 		       se_cmd->scsi_sense_length);
-		ret = copy_to_user(cmd->tvc_resp, &v_rsp, sizeof(v_rsp));
+		ret = memcpy_toiovecend(cmd->tvc_resp_iov, (unsigned char *)&v_rsp,
+					0, sizeof(v_rsp));
 		if (likely(ret == 0)) {
 			struct vhost_scsi_virtqueue *q;
 			vhost_add_used(cmd->tvc_vq, cmd->tvc_vq_desc, 0);
@@ -1159,7 +1160,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 
 		cmd->tvc_vhost = vs;
 		cmd->tvc_vq = vq;
-		cmd->tvc_resp = vq->iov[out].iov_base;
+		cmd->tvc_resp_iov = &vq->iov[out];
 
 		pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n",
 			cmd->tvc_cdb[0], cmd->tvc_lun);
-- 
1.9.1

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

* [PATCH 3/8] vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 2/8] vhost/scsi: Convert completion path to use memcpy_toiovecend Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len Nicholas A. Bellinger
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

This patch fixes vhost_scsi_handle_vq() failure cases that result in BUG_ON()
getting triggered when vhost_scsi_free_cmd() is called, and ->tvc_se_cmd has
not been initialized by target_submit_cmd_map_sgls().

It changes tcm_vhost_release_cmd() to use tcm_vhost_cmd->tvc_nexus for obtaining
se_session pointer reference.  Also, avoid calling put_page() on NULL sg->page
entries in vhost_scsi_map_to_sgl() failure path.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 52 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index a03ac41..9c5ac23 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -460,7 +460,7 @@ 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;
+	struct se_session *se_sess = tv_cmd->tvc_nexus->tvn_se_sess;
 	int i;
 
 	if (tv_cmd->tvc_sgl_count) {
@@ -859,9 +859,11 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 		ret = vhost_scsi_map_to_sgl(cmd, sg, sgl_count, &iov[i],
 					    cmd->tvc_upages, write);
 		if (ret < 0) {
-			for (i = 0; i < cmd->tvc_sgl_count; i++)
-				put_page(sg_page(&cmd->tvc_sgl[i]));
-
+			for (i = 0; i < cmd->tvc_sgl_count; i++) {
+				struct page *page = sg_page(&cmd->tvc_sgl[i]);
+				if (page)
+					put_page(page);
+			}
 			cmd->tvc_sgl_count = 0;
 			return ret;
 		}
@@ -900,9 +902,11 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
 		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]));
-
+			for (i = 0; i < cmd->tvc_prot_sgl_count; i++) {
+				struct page *page = sg_page(&cmd->tvc_prot_sgl[i]);
+				if (page)
+					put_page(page);
+			}
 			cmd->tvc_prot_sgl_count = 0;
 			return ret;
 		}
@@ -1060,12 +1064,14 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 		if (unlikely(vq->iov[0].iov_len < req_size)) {
 			pr_err("Expecting virtio-scsi header: %zu, got %zu\n",
 			       req_size, vq->iov[0].iov_len);
-			break;
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
 		}
 		ret = memcpy_fromiovecend(req, &vq->iov[0], 0, req_size);
 		if (unlikely(ret)) {
 			vq_err(vq, "Faulted on virtio_scsi_cmd_req\n");
-			break;
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
 		}
 
 		/* virtio-scsi spec requires byte 0 of the lun to be 1 */
@@ -1096,14 +1102,16 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 				if (data_direction != DMA_TO_DEVICE) {
 					vq_err(vq, "Received non zero do_pi_niov"
 						", but wrong data_direction\n");
-					goto err_cmd;
+					vhost_scsi_send_bad_target(vs, vq, head, out);
+					continue;
 				}
 				prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesout);
 			} else if (v_req_pi.pi_bytesin) {
 				if (data_direction != DMA_FROM_DEVICE) {
 					vq_err(vq, "Received non zero di_pi_niov"
 						", but wrong data_direction\n");
-					goto err_cmd;
+					vhost_scsi_send_bad_target(vs, vq, head, out);
+					continue;
 				}
 				prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesin);
 			}
@@ -1143,7 +1151,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 			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;
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
 		}
 
 		cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr,
@@ -1152,7 +1161,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 		if (IS_ERR(cmd)) {
 			vq_err(vq, "vhost_scsi_get_tag failed %ld\n",
 					PTR_ERR(cmd));
-			goto err_cmd;
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
 		}
 
 		pr_debug("Allocated tv_cmd: %p exp_data_len: %d, data_direction"
@@ -1172,7 +1182,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 			if (unlikely(ret)) {
 				vq_err(vq, "Failed to map iov to"
 					" prot_sgl\n");
-				goto err_free;
+				tcm_vhost_release_cmd(&cmd->tvc_se_cmd);
+				vhost_scsi_send_bad_target(vs, vq, head, out);
+				continue;
 			}
 		}
 		if (data_direction != DMA_NONE) {
@@ -1181,7 +1193,9 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 					data_direction == DMA_FROM_DEVICE);
 			if (unlikely(ret)) {
 				vq_err(vq, "Failed to map iov to sgl\n");
-				goto err_free;
+				tcm_vhost_release_cmd(&cmd->tvc_se_cmd);
+				vhost_scsi_send_bad_target(vs, vq, head, out);
+				continue;
 			}
 		}
 		/*
@@ -1199,14 +1213,6 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 		INIT_WORK(&cmd->work, tcm_vhost_submission_work);
 		queue_work(tcm_vhost_workqueue, &cmd->work);
 	}
-
-	mutex_unlock(&vq->mutex);
-	return;
-
-err_free:
-	vhost_scsi_free_cmd(cmd);
-err_cmd:
-	vhost_scsi_send_bad_target(vs, vq, head, out);
 out:
 	mutex_unlock(&vq->mutex);
 }
-- 
1.9.1


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

* [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (2 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 3/8] vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30 10:51   ` Michael S. Tsirkin
  2015-01-30  8:12 ` [PATCH 5/8] vhost/scsi: Add common vhost_scsi_queue_desc code Nicholas A. Bellinger
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

This patch changes vhost_scsi_map_to_sgl() parameters to accept virtio
iovec ptr + len when determing pages_nr.

This is currently done with iov_num_pages() -> PAGE_ALIGN, so allow
the same parameters as well.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 37 +++++++++++++++----------------------
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 9c5ac23..049e603 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -220,10 +220,10 @@ static struct workqueue_struct *tcm_vhost_workqueue;
 static DEFINE_MUTEX(tcm_vhost_mutex);
 static LIST_HEAD(tcm_vhost_list);
 
-static int iov_num_pages(struct iovec *iov)
+static int iov_num_pages(void __user *iov_base, size_t iov_len)
 {
-	return (PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
-	       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT;
+	return (PAGE_ALIGN((unsigned long)iov_base + iov_len) -
+	       ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT;
 }
 
 static void tcm_vhost_done_inflight(struct kref *kref)
@@ -777,25 +777,18 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg,
  * Returns the number of scatterlist entries used or -errno on error.
  */
 static int
-vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
+vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *cmd,
+		      void __user *ptr,
+		      size_t len,
 		      struct scatterlist *sgl,
-		      unsigned int sgl_count,
-		      struct iovec *iov,
-		      struct page **pages,
 		      bool write)
 {
-	unsigned int npages = 0, pages_nr, offset, nbytes;
+	unsigned int npages = 0, offset, nbytes;
+	unsigned int pages_nr = iov_num_pages(ptr, len);
 	struct scatterlist *sg = sgl;
-	void __user *ptr = iov->iov_base;
-	size_t len = iov->iov_len;
+	struct page **pages = cmd->tvc_upages;
 	int ret, i;
 
-	pages_nr = iov_num_pages(iov);
-	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_UPAGES) {
 		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
 		       " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n",
@@ -840,7 +833,7 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 	int ret, i;
 
 	for (i = 0; i < niov; i++)
-		sgl_count += iov_num_pages(&iov[i]);
+		sgl_count += iov_num_pages(iov[i].iov_base, iov[i].iov_len);
 
 	if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
 		pr_err("vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than"
@@ -856,8 +849,8 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
 	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],
-					    cmd->tvc_upages, write);
+		ret = vhost_scsi_map_to_sgl(cmd, iov[i].iov_base, iov[i].iov_len,
+					    sg, write);
 		if (ret < 0) {
 			for (i = 0; i < cmd->tvc_sgl_count; i++) {
 				struct page *page = sg_page(&cmd->tvc_sgl[i]);
@@ -884,7 +877,7 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
 	int ret, i;
 
 	for (i = 0; i < niov; i++)
-		prot_sgl_count += iov_num_pages(&iov[i]);
+		prot_sgl_count += iov_num_pages(iov[i].iov_base, iov[i].iov_len);
 
 	if (prot_sgl_count > TCM_VHOST_PREALLOC_PROT_SGLS) {
 		pr_err("vhost_scsi_map_iov_to_prot() sgl_count: %u greater than"
@@ -899,8 +892,8 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
 	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);
+		ret = vhost_scsi_map_to_sgl(cmd, iov[i].iov_base, iov[i].iov_len,
+					    prot_sg, write);
 		if (ret < 0) {
 			for (i = 0; i < cmd->tvc_prot_sgl_count; i++) {
 				struct page *page = sg_page(&cmd->tvc_prot_sgl[i]);
-- 
1.9.1

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

* [PATCH 5/8] vhost/scsi: Add common vhost_scsi_queue_desc code
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (3 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 6/8] vhost/scsi: Add ANY_LAYOUT prerequisites Nicholas A. Bellinger
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

Move logic for typical vhost_scsi_handle_vq() -> tcm_vhost_workqueue ->
tcm_vhost_submission_work()  dispatch into vhost_scsi_queue_desc().

Can be shared by vhost_scsi_handle_vqal() code.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 049e603..756a893 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -963,6 +963,24 @@ vhost_scsi_send_bad_target(struct vhost_scsi *vs,
 		pr_err("Faulted on virtio_scsi_cmd_resp\n");
 }
 
+static void vhost_scsi_queue_desc(struct tcm_vhost_cmd *cmd, int desc)
+{
+	/*
+	 * Save the descriptor from vhost_get_vq_desc() to be used to
+	 * complete the virtio-scsi request in TCM callback context via
+	 * tcm_vhost_queue_data_in() and tcm_vhost_queue_status()
+	 */
+	cmd->tvc_vq_desc = desc;
+	/*
+	 * Dispatch cmd descriptor for cmwq execution in process
+	 * context provided by tcm_vhost_workqueue.  This also ensures
+	 * cmd is executed on the same kworker CPU as this vhost
+	 * thread to gain positive L2 cache locality effects.
+	 */
+	INIT_WORK(&cmd->work, tcm_vhost_submission_work);
+	queue_work(tcm_vhost_workqueue, &cmd->work);
+}
+
 static void
 vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 {
@@ -1191,20 +1209,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 				continue;
 			}
 		}
-		/*
-		 * Save the descriptor from vhost_get_vq_desc() to be used to
-		 * complete the virtio-scsi request in TCM callback context via
-		 * tcm_vhost_queue_data_in() and tcm_vhost_queue_status()
-		 */
-		cmd->tvc_vq_desc = head;
-		/*
-		 * Dispatch tv_cmd descriptor for cmwq execution in process
-		 * context provided by tcm_vhost_workqueue.  This also ensures
-		 * tv_cmd is executed on the same kworker CPU as this vhost
-		 * thread to gain positive L2 cache locality effects..
-		 */
-		INIT_WORK(&cmd->work, tcm_vhost_submission_work);
-		queue_work(tcm_vhost_workqueue, &cmd->work);
+		vhost_scsi_queue_desc(cmd, head);
 	}
 out:
 	mutex_unlock(&vq->mutex);
-- 
1.9.1

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

* [PATCH 6/8] vhost/scsi: Add ANY_LAYOUT prerequisites
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (4 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 5/8] vhost/scsi: Add common vhost_scsi_queue_desc code Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 7/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

This patch adds ANY_LAYOUT prerequisites logic for accepting a set of
protection + data payloads via iovec + offset.  Also includes helpers
for calcuating SGLs + invoking vhost_scsi_map_to_sgl() with a known
number of iovecs.

Required by ANY_LAYOUT processing when struct iovec may be offset into
the first outgoing virtio-scsi request header.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 756a893..d2208a41 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -909,6 +909,111 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
 	return 0;
 }
 
+static int
+vhost_scsi_calc_sgls(struct iovec *iov, size_t off, size_t bytes,
+		     int *niov, int max_sgls)
+{
+	size_t tmp = 0;
+	int sgl_count = 0;
+
+	*niov = 0;
+
+	while (tmp < bytes) {
+		void __user *base = iov[*niov].iov_base + off;
+		size_t len = iov[(*niov)++].iov_len - off;
+
+		sgl_count += iov_num_pages(base, len);
+		tmp += min(len, bytes);
+		off = 0;
+	}
+	if (sgl_count > max_sgls) {
+		pr_err("%s: requested sgl_count: %d exceeds pre-allocated"
+		       " max_sgls: %d\n", __func__, sgl_count, max_sgls);
+		return -ENOBUFS;
+	}
+	return sgl_count;
+}
+
+static int
+vhost_scsi_iov_to_sgl(struct tcm_vhost_cmd *cmd, bool write,
+		      struct iovec *iov, size_t iov_off, int niov,
+		      struct scatterlist *sg, int sg_count)
+{
+	int i, ret;
+
+	for (i = 0; i < niov; i++) {
+		void __user *base = iov[i].iov_base + iov_off;
+		size_t len = iov[i].iov_len - iov_off;
+
+		ret = vhost_scsi_map_to_sgl(cmd, base, len, sg, write);
+		if (ret < 0) {
+			for (i = 0; i < sg_count; i++) {
+				struct page *page = sg_page(&sg[i]);
+				if (page)
+					put_page(page);
+			}
+			return ret;
+		}
+		sg += ret;
+		iov_off = 0;
+	}
+	return 0;
+}
+
+static int
+vhost_scsi_mapal(struct tcm_vhost_cmd *cmd,
+		 size_t prot_bytes, struct iovec *prot_iov, size_t prot_off,
+		 size_t data_bytes, struct iovec *data_iov, size_t data_off)
+{
+	int data_sgl_count = 0, niov, ret;
+	bool write = (cmd->tvc_data_direction == DMA_FROM_DEVICE);
+
+	if (prot_bytes) {
+		int prot_sgl_count;
+
+		if (!prot_iov) {
+			pr_err("%s: prot_iov is NULL, but prot_bytes: %zu"
+			       "present\n", __func__, prot_bytes);
+			return -EINVAL;
+		}
+		prot_sgl_count = vhost_scsi_calc_sgls(prot_iov, prot_off,
+						      prot_bytes, &niov,
+						      TCM_VHOST_PREALLOC_PROT_SGLS);
+		if (prot_sgl_count < 0)
+			return prot_sgl_count;
+
+		sg_init_table(cmd->tvc_prot_sgl, prot_sgl_count);
+		cmd->tvc_prot_sgl_count = prot_sgl_count;
+		pr_debug("%s prot_sg %p prot_sgl_count %u\n", __func__,
+			 cmd->tvc_prot_sgl, cmd->tvc_prot_sgl_count);
+
+		ret = vhost_scsi_iov_to_sgl(cmd, write, prot_iov, prot_off,
+					    niov, cmd->tvc_prot_sgl,
+					    prot_sgl_count);
+		if (ret < 0) {
+			cmd->tvc_prot_sgl_count = 0;
+			return ret;
+		}
+	}
+	if (!data_iov) {
+		pr_err("%s: data_iov is NULL, but data_bytes: %zu present\n",
+		       __func__, data_bytes);
+		return -EINVAL;
+	}
+	data_sgl_count = vhost_scsi_calc_sgls(data_iov, data_off, data_bytes,
+					      &niov, TCM_VHOST_PREALLOC_SGLS);
+	if (data_sgl_count < 0)
+		return data_sgl_count;
+
+	sg_init_table(cmd->tvc_sgl, data_sgl_count);
+	cmd->tvc_sgl_count = data_sgl_count;
+	pr_debug("%s data_sg %p data_sgl_count %u\n", __func__,
+		  cmd->tvc_sgl, cmd->tvc_sgl_count);
+
+	return vhost_scsi_iov_to_sgl(cmd, write, data_iov, data_off,
+				     niov, cmd->tvc_sgl, data_sgl_count);
+}
+
 static void tcm_vhost_submission_work(struct work_struct *work)
 {
 	struct tcm_vhost_cmd *cmd =
-- 
1.9.1


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

* [PATCH 7/8] vhost/scsi: Add ANY_LAYOUT support
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (5 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 6/8] vhost/scsi: Add ANY_LAYOUT prerequisites Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-01-30  8:12 ` [PATCH 8/8] vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits Nicholas A. Bellinger
  2015-02-02  8:15 ` [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Christoph Hellwig
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

This patch adds initial ANY_LAYOUT support with a new vhost_virtqueue
callback in vhost_scsi_handle_vqal().

It calculates data_direction + exp_data_len for the new tcm_vhost_cmd
descriptor by walking both outgoing + incoming iovecs, assuming the
layout of outgoing request header + T10_PI + Data payload comes first.

It also uses memcpy_fromiovec_out() to copy leading virtio-scsi
request header that may or may not include SCSI CDB, that returns a
re-calculated iovec to start of T10_PI or Data SGL memory.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 267 insertions(+)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index d2208a41..206f4ef 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1087,6 +1087,273 @@ static void vhost_scsi_queue_desc(struct tcm_vhost_cmd *cmd, int desc)
 }
 
 static void
+vhost_scsi_handle_vqal(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;
+	struct iovec *iov, *iov_out, *prot_iov, *data_iov;
+	u64 tag;
+	u32 exp_data_len, data_direction;
+	unsigned out, in, i;
+	int head, ret, prot_bytes, iov_off, data_off, prot_off;
+	size_t req_size, rsp_size = sizeof(struct virtio_scsi_cmd_resp);
+	size_t out_size, in_size;
+	u16 lun;
+	u8 *target, *lunp, task_attr;
+	bool t10_pi = vhost_has_feature(vq, VIRTIO_SCSI_F_T10_PI);
+	void *req, *cdb;
+
+	mutex_lock(&vq->mutex);
+	/*
+	 * We can handle the vq only after the endpoint is setup by calling the
+	 * VHOST_SCSI_SET_ENDPOINT ioctl.
+	 */
+	vs_tpg = vq->private_data;
+	if (!vs_tpg)
+		goto out;
+
+	vhost_disable_notify(&vs->dev, vq);
+
+	for (;;) {
+		head = vhost_get_vq_desc(vq, vq->iov,
+					 ARRAY_SIZE(vq->iov), &out, &in,
+					 NULL, NULL);
+		pr_debug("vhost_get_vq_desc: head: %d, out: %u in: %u\n",
+			 head, out, in);
+		/* On error, stop handling until the next kick. */
+		if (unlikely(head < 0))
+			break;
+		/* Nothing new?  Wait for eventfd to tell us they refilled. */
+		if (head == vq->num) {
+			if (unlikely(vhost_enable_notify(&vs->dev, vq))) {
+				vhost_disable_notify(&vs->dev, vq);
+				continue;
+			}
+			break;
+		}
+		/*
+		 * Setup pointers and values based upon different virtio-scsi
+		 * request header if T10_PI is enabled in KVM guest.
+		 */
+		if (t10_pi) {
+			req = &v_req_pi;
+			req_size = sizeof(v_req_pi);
+			lunp = &v_req_pi.lun[0];
+			target = &v_req_pi.lun[1];
+		} else {
+			req = &v_req;
+			req_size = sizeof(v_req);
+			lunp = &v_req.lun[0];
+			target = &v_req.lun[1];
+		}
+		/*
+		 * Determine data_direction for ANY_LAYOUT by calculating the
+		 * total outgoing iovec sizes / incoming iovec sizes vs.
+		 * virtio-scsi request / response headers respectively.
+		 *
+		 * FIXME: Not correct for BIDI operation
+		 */
+		out_size = in_size = 0;
+		for (i = 0; i < out; i++)
+			out_size += vq->iov[i].iov_len;
+		for (i = out; i < out + in; i++)
+			in_size += vq->iov[i].iov_len;
+		/*
+		 * Any associated T10_PI bytes for the outgoing / incoming
+		 * payloads are included in calculation of exp_data_len here.
+		 */
+		if (out_size > req_size) {
+			data_direction = DMA_TO_DEVICE;
+			exp_data_len = out_size - req_size;
+		} else if (in_size > rsp_size) {
+			data_direction = DMA_FROM_DEVICE;
+			exp_data_len = in_size - rsp_size;
+		} else {
+			data_direction = DMA_NONE;
+			exp_data_len = 0;
+		}
+		/*
+		 * Copy over the virtio-scsi request header, which when
+		 * ANY_LAYOUT is enabled may span multiple iovecs, or a
+		 * single iovec may contain both the header + incoming
+		 * WRITE payloads.
+		 *
+		 * memcpy_fromiovec_out() is modifying the iovecs as it
+		 * copies over req_size bytes into req, so the returned
+		 * iov_out will contain the correct start + offset of the
+		 * incoming WRITE payload, if DMA_TO_DEVICE is set.
+		 */
+		ret = memcpy_fromiovec_out(req, &vq->iov[0], &iov_out, req_size);
+		if (unlikely(ret)) {
+			vq_err(vq, "Faulted on virtio_scsi_cmd_req\n");
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+
+		/* virtio-scsi spec requires byte 0 of the lun to be 1 */
+		if (unlikely(*lunp != 1)) {
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+
+		tpg = ACCESS_ONCE(vs_tpg[*target]);
+		if (unlikely(!tpg)) {
+			/* Target does not exist, fail the request */
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+		/*
+		 * Determine start of T10_PI or data payload iovec in ANY_LAYOUT
+		 * mode based upon data_direction.
+		 *
+		 * For DMA_TO_DEVICE, this is iov_out from memcpy_fromiovec_out()
+		 * with the already recalculated iov_base + iov_len.
+		 *
+		 * For DMA_FROM_DEVICE, the iovec will be just past the end
+		 * of the virtio-scsi response header in either the same
+		 * or immediately following iovec.
+		 */
+		iov = data_iov = prot_iov = NULL;
+		iov_off = data_off = prot_off = 0;
+
+		if (data_direction == DMA_TO_DEVICE) {
+			iov = iov_out;
+		} else if (data_direction == DMA_FROM_DEVICE) {
+			int tmp_rsp_size = rsp_size;
+
+			for (i = out; i < out + in; i++) {
+				if (vq->iov[i].iov_len > tmp_rsp_size) {
+					iov = &vq->iov[i];
+					iov_off = tmp_rsp_size;
+					break;
+				} else if (vq->iov[i].iov_len == tmp_rsp_size) {
+					iov = &vq->iov[i+1];
+					break;
+				} else {
+					tmp_rsp_size -= vq->iov[i].iov_len;
+				}
+			}
+		}
+		/*
+		 * If T10_PI header is present, setup prot_iov + prot_off values
+		 * then recalculate data_iov + data_off for vhost_scsi_mapal()
+		 * mapping from host scatterlists via get_user_pages_fast().
+		 */
+		prot_bytes = 0;
+
+		if (t10_pi) {
+			int i = 0, tmp_prot_bytes;
+
+			if (v_req_pi.pi_bytesout) {
+				if (data_direction != DMA_TO_DEVICE) {
+					vq_err(vq, "Received non zero do_pi_niov"
+						", but wrong data_direction\n");
+					vhost_scsi_send_bad_target(vs, vq, head, out);
+					continue;
+				}
+				prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesout);
+			} else if (v_req_pi.pi_bytesin) {
+				if (data_direction != DMA_FROM_DEVICE) {
+					vq_err(vq, "Received non zero di_pi_niov"
+						", but wrong data_direction\n");
+					vhost_scsi_send_bad_target(vs, vq, head, out);
+					continue;
+				}
+				prot_bytes = vhost32_to_cpu(vq, v_req_pi.pi_bytesin);
+			}
+			/*
+			 * Set prot_iov + prot_off values used by the iovec ->
+			 * SGL mapping logic, then calculate the start of data
+			 * payload after T10_PI and save to data_iov + data_off.
+			 */
+			data_iov = prot_iov = iov;
+			data_off = prot_off = iov_off;
+			tmp_prot_bytes = prot_bytes;
+
+			while (tmp_prot_bytes) {
+				int iov_len = prot_iov[i].iov_len - iov_off;
+				int len = min(iov_len, tmp_prot_bytes);
+
+				if (tmp_prot_bytes -= len) {
+					i++;
+					iov_off = 0;
+					continue;
+				}
+				if (iov_len > len) {
+					data_iov = &prot_iov[i];
+					data_off = len;
+				} else if (iov_len == len) {
+					data_iov = &prot_iov[i+1];
+					data_off = 0;
+				}
+			}
+
+			exp_data_len -= prot_bytes;
+			tag = vhost64_to_cpu(vq, 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 {
+			data_iov = iov;
+			data_off = iov_off;
+
+			tag = vhost64_to_cpu(vq, 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;
+		}
+		/*
+		 * Check that the recieved CDB size does not exceeded our
+		 * hardcoded max for vhost-scsi, then get a pre-allocated
+		 * cmd descriptor for the incoming virtio-scsi tag.
+		 *
+		 * 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);
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+		cmd = vhost_scsi_get_tag(vq, tpg, cdb, tag, lun, task_attr,
+					 exp_data_len + prot_bytes,
+					 data_direction);
+		if (IS_ERR(cmd)) {
+			vq_err(vq, "vhost_scsi_get_tag failed %ld\n",
+			       PTR_ERR(cmd));
+			vhost_scsi_send_bad_target(vs, vq, head, out);
+			continue;
+		}
+		cmd->tvc_vhost = vs;
+		cmd->tvc_vq = vq;
+		cmd->tvc_resp_iov = &vq->iov[out];
+
+		pr_debug("vhost_scsi got command opcode: %#02x, lun: %d\n",
+			 cmd->tvc_cdb[0], cmd->tvc_lun);
+		pr_debug("cmd: %p exp_data_len: %d, prot_bytes: %d data_direction:"
+			 " %d\n", cmd, exp_data_len, prot_bytes, data_direction);
+
+		if (data_direction != DMA_NONE) {
+			ret = vhost_scsi_mapal(cmd, prot_bytes, prot_iov, prot_off,
+					       exp_data_len, data_iov, data_off);
+			if (unlikely(ret)) {
+				vq_err(vq, "Failed to map iov to sgl\n");
+				tcm_vhost_release_cmd(&cmd->tvc_se_cmd);
+				vhost_scsi_send_bad_target(vs, vq, head, out);
+				continue;
+			}
+		}
+		vhost_scsi_queue_desc(cmd, head);
+	}
+out:
+	mutex_unlock(&vq->mutex);
+}
+
+static void
 vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
 {
 	struct tcm_vhost_tpg **vs_tpg;
-- 
1.9.1


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

* [PATCH 8/8] vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (6 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 7/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
@ 2015-01-30  8:12 ` Nicholas A. Bellinger
  2015-02-02  8:15 ` [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Christoph Hellwig
  8 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-01-30  8:12 UTC (permalink / raw)
  To: target-devel
  Cc: linux-scsi, kvm-devel, Paolo Bonzini, Michael S. Tsirkin,
	Nicholas Bellinger

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

Signal support of VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits
required for virtio-scsi 1.0 spec layout requirements.

Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
 drivers/vhost/scsi.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 206f4ef..a773af3 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -171,7 +171,9 @@ enum {
 /* Note: can't set VIRTIO_F_VERSION_1 yet, since that implies ANY_LAYOUT. */
 enum {
 	VHOST_SCSI_FEATURES = VHOST_FEATURES | (1ULL << VIRTIO_SCSI_F_HOTPLUG) |
-					       (1ULL << VIRTIO_SCSI_F_T10_PI)
+					       (1ULL << VIRTIO_SCSI_F_T10_PI) |
+					       (1ULL << VIRTIO_F_ANY_LAYOUT) |
+					       (1ULL << VIRTIO_F_VERSION_1)
 };
 
 #define VHOST_SCSI_MAX_TARGET	256
@@ -1644,7 +1646,10 @@ static void vhost_scsi_handle_kick(struct vhost_work *work)
 						poll.work);
 	struct vhost_scsi *vs = container_of(vq->dev, struct vhost_scsi, dev);
 
-	vhost_scsi_handle_vq(vs, vq);
+	if (vhost_has_feature(vq, VIRTIO_F_ANY_LAYOUT))
+		vhost_scsi_handle_vqal(vs, vq);
+	else
+		vhost_scsi_handle_vq(vs, vq);
 }
 
 static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
-- 
1.9.1

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

* Re: [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function
  2015-01-30  8:12 ` [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function Nicholas A. Bellinger
@ 2015-01-30  9:33   ` Paolo Bonzini
  2015-02-01  7:15     ` Nicholas A. Bellinger
  0 siblings, 1 reply; 15+ messages in thread
From: Paolo Bonzini @ 2015-01-30  9:33 UTC (permalink / raw)
  To: Nicholas A. Bellinger, target-devel
  Cc: linux-scsi, kvm-devel, Michael S. Tsirkin, Nicholas Bellinger



On 30/01/2015 09:12, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> This patch adds a new memcpy_fromiovec_out() library function which modifies
> the passed *iov following memcpy_fromiovec(), but also returns the next current
> iovec pointer via **iov_out.
> 
> This is useful for vhost ANY_LAYOUT support when guests are allowed to generate
> incoming virtio request headers combined with subsequent SGL payloads into a
> single iovec.
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
>  include/linux/uio.h |  2 ++
>  lib/iovec.c         | 27 +++++++++++++++++++++++++++
>  2 files changed, 29 insertions(+)
> 
> diff --git a/include/linux/uio.h b/include/linux/uio.h
> index 1c5e453..3e4473d 100644
> --- a/include/linux/uio.h
> +++ b/include/linux/uio.h
> @@ -136,6 +136,8 @@ size_t csum_and_copy_to_iter(void *addr, size_t bytes, __wsum *csum, struct iov_
>  size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i);
>  
>  int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
> +int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
> +			 struct iovec **iov_out, int len);
>  int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov,
>  			int offset, int len);
>  int memcpy_toiovecend(const struct iovec *v, unsigned char *kdata,
> diff --git a/lib/iovec.c b/lib/iovec.c
> index 2d99cb4..6a813dd 100644
> --- a/lib/iovec.c
> +++ b/lib/iovec.c
> @@ -28,6 +28,33 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
>  EXPORT_SYMBOL(memcpy_fromiovec);
>  
>  /*
> + *	Copy iovec to kernel, saving the current iov to *iov_out.
> + *	Returns -EFAULT on error.

Perhaps document that iov is modified, zeroing everything in [iov,
*iov_out) and possibly removing the front of *iov_out?

Paolo

> + */
> +
> +int memcpy_fromiovec_out(unsigned char *kdata, struct iovec *iov,
> +			 struct iovec **iov_out, int len)
> +{
> +	while (len > 0) {
> +		if (iov->iov_len) {
> +			int copy = min_t(unsigned int, len, iov->iov_len);
> +			if (copy_from_user(kdata, iov->iov_base, copy))
> +				return -EFAULT;
> +			len -= copy;
> +			kdata += copy;
> +			iov->iov_base += copy;
> +			iov->iov_len -= copy;
> +		}
> +		if (!iov->iov_len)
> +			iov++;
> +	}
> +	*iov_out = iov;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(memcpy_fromiovec_out);
> +
> +/*
>   *	Copy kernel to iovec. Returns -EFAULT on error.
>   */
>  
> 

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

* Re: [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len
  2015-01-30  8:12 ` [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len Nicholas A. Bellinger
@ 2015-01-30 10:51   ` Michael S. Tsirkin
  2015-02-01  7:24     ` Nicholas A. Bellinger
  0 siblings, 1 reply; 15+ messages in thread
From: Michael S. Tsirkin @ 2015-01-30 10:51 UTC (permalink / raw)
  To: Nicholas A. Bellinger
  Cc: target-devel, linux-scsi, kvm-devel, Paolo Bonzini, Nicholas Bellinger

On Fri, Jan 30, 2015 at 08:12:28AM +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
> 
> This patch changes vhost_scsi_map_to_sgl() parameters to accept virtio
> iovec ptr + len when determing pages_nr.
> 
> This is currently done with iov_num_pages() -> PAGE_ALIGN, so allow
> the same parameters as well.
> 
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> ---
>  drivers/vhost/scsi.c | 37 +++++++++++++++----------------------
>  1 file changed, 15 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index 9c5ac23..049e603 100644
> --- a/drivers/vhost/scsi.c
> +++ b/drivers/vhost/scsi.c
> @@ -220,10 +220,10 @@ static struct workqueue_struct *tcm_vhost_workqueue;
>  static DEFINE_MUTEX(tcm_vhost_mutex);
>  static LIST_HEAD(tcm_vhost_list);
>  
> -static int iov_num_pages(struct iovec *iov)
> +static int iov_num_pages(void __user *iov_base, size_t iov_len)
>  {
> -	return (PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
> -	       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT;
> +	return (PAGE_ALIGN((unsigned long)iov_base + iov_len) -
> +	       ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT;
>  }
>  
>  static void tcm_vhost_done_inflight(struct kref *kref)
> @@ -777,25 +777,18 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg,
>   * Returns the number of scatterlist entries used or -errno on error.
>   */
>  static int
> -vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
> +vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *cmd,
> +		      void __user *ptr,
> +		      size_t len,
>  		      struct scatterlist *sgl,
> -		      unsigned int sgl_count,
> -		      struct iovec *iov,
> -		      struct page **pages,
>  		      bool write)
>  {
> -	unsigned int npages = 0, pages_nr, offset, nbytes;
> +	unsigned int npages = 0, offset, nbytes;
> +	unsigned int pages_nr = iov_num_pages(ptr, len);
>  	struct scatterlist *sg = sgl;
> -	void __user *ptr = iov->iov_base;
> -	size_t len = iov->iov_len;
> +	struct page **pages = cmd->tvc_upages;
>  	int ret, i;
>  
> -	pages_nr = iov_num_pages(iov);
> -	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_UPAGES) {
>  		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
>  		       " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n",
> @@ -840,7 +833,7 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
>  	int ret, i;
>  
>  	for (i = 0; i < niov; i++)
> -		sgl_count += iov_num_pages(&iov[i]);
> +		sgl_count += iov_num_pages(iov[i].iov_base, iov[i].iov_len);
>  

A helper function for this loop seems in order as well?


>  	if (sgl_count > TCM_VHOST_PREALLOC_SGLS) {
>  		pr_err("vhost_scsi_map_iov_to_sgl() sgl_count: %u greater than"
> @@ -856,8 +849,8 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
>  	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],
> -					    cmd->tvc_upages, write);
> +		ret = vhost_scsi_map_to_sgl(cmd, iov[i].iov_base, iov[i].iov_len,
> +					    sg, write);
>  		if (ret < 0) {
>  			for (i = 0; i < cmd->tvc_sgl_count; i++) {
>  				struct page *page = sg_page(&cmd->tvc_sgl[i]);
> @@ -884,7 +877,7 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
>  	int ret, i;
>  
>  	for (i = 0; i < niov; i++)
> -		prot_sgl_count += iov_num_pages(&iov[i]);
> +		prot_sgl_count += iov_num_pages(iov[i].iov_base, iov[i].iov_len);
>  
>  	if (prot_sgl_count > TCM_VHOST_PREALLOC_PROT_SGLS) {
>  		pr_err("vhost_scsi_map_iov_to_prot() sgl_count: %u greater than"
> @@ -899,8 +892,8 @@ vhost_scsi_map_iov_to_prot(struct tcm_vhost_cmd *cmd,
>  	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);
> +		ret = vhost_scsi_map_to_sgl(cmd, iov[i].iov_base, iov[i].iov_len,
> +					    prot_sg, write);
>  		if (ret < 0) {
>  			for (i = 0; i < cmd->tvc_prot_sgl_count; i++) {
>  				struct page *page = sg_page(&cmd->tvc_prot_sgl[i]);
> -- 
> 1.9.1

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

* Re: [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function
  2015-01-30  9:33   ` Paolo Bonzini
@ 2015-02-01  7:15     ` Nicholas A. Bellinger
  0 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-02-01  7:15 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi, kvm-devel,
	Michael S. Tsirkin

On Fri, 2015-01-30 at 10:33 +0100, Paolo Bonzini wrote:
> 
> On 30/01/2015 09:12, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > 
> > This patch adds a new memcpy_fromiovec_out() library function which modifies
> > the passed *iov following memcpy_fromiovec(), but also returns the next current
> > iovec pointer via **iov_out.
> > 
> > This is useful for vhost ANY_LAYOUT support when guests are allowed to generate
> > incoming virtio request headers combined with subsequent SGL payloads into a
> > single iovec.
> > 
> > Cc: Michael S. Tsirkin <mst@redhat.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> > ---
> >  include/linux/uio.h |  2 ++
> >  lib/iovec.c         | 27 +++++++++++++++++++++++++++
> >  2 files changed, 29 insertions(+)
> > 

<SNIP>

> > --- a/lib/iovec.c
> > +++ b/lib/iovec.c
> > @@ -28,6 +28,33 @@ int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
> >  EXPORT_SYMBOL(memcpy_fromiovec);
> >  
> >  /*
> > + *	Copy iovec to kernel, saving the current iov to *iov_out.
> > + *	Returns -EFAULT on error.
> 
> Perhaps document that iov is modified, zeroing everything in [iov,
> *iov_out) and possibly removing the front of *iov_out?
> 

Sure, updated the read the following:

 *      Copy iovec to kernel, modifying the passed *iov entries.
 *
 *      Save **iov_out for the caller to use upon return, that may either
 *      contain the current entry with a re-calculated iov_base + iov_len
 *      or next unmodified entry.
 *
 *      Also note that any iovec entries preceding the final *iov_out are
 *      zeroed by copy_from_user().

Thank you,

--nab

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

* Re: [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len
  2015-01-30 10:51   ` Michael S. Tsirkin
@ 2015-02-01  7:24     ` Nicholas A. Bellinger
  0 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-02-01  7:24 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi, kvm-devel,
	Paolo Bonzini

On Fri, 2015-01-30 at 12:51 +0200, Michael S. Tsirkin wrote:
> On Fri, Jan 30, 2015 at 08:12:28AM +0000, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > 
> > This patch changes vhost_scsi_map_to_sgl() parameters to accept virtio
> > iovec ptr + len when determing pages_nr.
> > 
> > This is currently done with iov_num_pages() -> PAGE_ALIGN, so allow
> > the same parameters as well.
> > 
> > Cc: Michael S. Tsirkin <mst@redhat.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
> > ---
> >  drivers/vhost/scsi.c | 37 +++++++++++++++----------------------
> >  1 file changed, 15 insertions(+), 22 deletions(-)
> > 
> > diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> > index 9c5ac23..049e603 100644
> > --- a/drivers/vhost/scsi.c
> > +++ b/drivers/vhost/scsi.c
> > @@ -220,10 +220,10 @@ static struct workqueue_struct *tcm_vhost_workqueue;
> >  static DEFINE_MUTEX(tcm_vhost_mutex);
> >  static LIST_HEAD(tcm_vhost_list);
> >  
> > -static int iov_num_pages(struct iovec *iov)
> > +static int iov_num_pages(void __user *iov_base, size_t iov_len)
> >  {
> > -	return (PAGE_ALIGN((unsigned long)iov->iov_base + iov->iov_len) -
> > -	       ((unsigned long)iov->iov_base & PAGE_MASK)) >> PAGE_SHIFT;
> > +	return (PAGE_ALIGN((unsigned long)iov_base + iov_len) -
> > +	       ((unsigned long)iov_base & PAGE_MASK)) >> PAGE_SHIFT;
> >  }
> >  
> >  static void tcm_vhost_done_inflight(struct kref *kref)
> > @@ -777,25 +777,18 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct tcm_vhost_tpg *tpg,
> >   * Returns the number of scatterlist entries used or -errno on error.
> >   */
> >  static int
> > -vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *tv_cmd,
> > +vhost_scsi_map_to_sgl(struct tcm_vhost_cmd *cmd,
> > +		      void __user *ptr,
> > +		      size_t len,
> >  		      struct scatterlist *sgl,
> > -		      unsigned int sgl_count,
> > -		      struct iovec *iov,
> > -		      struct page **pages,
> >  		      bool write)
> >  {
> > -	unsigned int npages = 0, pages_nr, offset, nbytes;
> > +	unsigned int npages = 0, offset, nbytes;
> > +	unsigned int pages_nr = iov_num_pages(ptr, len);
> >  	struct scatterlist *sg = sgl;
> > -	void __user *ptr = iov->iov_base;
> > -	size_t len = iov->iov_len;
> > +	struct page **pages = cmd->tvc_upages;
> >  	int ret, i;
> >  
> > -	pages_nr = iov_num_pages(iov);
> > -	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_UPAGES) {
> >  		pr_err("vhost_scsi_map_to_sgl() pages_nr: %u greater than"
> >  		       " preallocated TCM_VHOST_PREALLOC_UPAGES: %u\n",
> > @@ -840,7 +833,7 @@ vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *cmd,
> >  	int ret, i;
> >  
> >  	for (i = 0; i < niov; i++)
> > -		sgl_count += iov_num_pages(&iov[i]);
> > +		sgl_count += iov_num_pages(iov[i].iov_base, iov[i].iov_len);
> >  
> 
> A helper function for this loop seems in order as well?
> 

I didn't bother with this, as it's only used by the legacy !ANY_LAYOUT
related code-path.

Also, I don't see a reason at this point to keep the !ANY_LAYOUT bits
around for >= v3.20 code, so for -v2 I'll just drop the legacy code
(including the above) all together.

Thank you,

--nab

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

* Re: [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support
  2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
                   ` (7 preceding siblings ...)
  2015-01-30  8:12 ` [PATCH 8/8] vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits Nicholas A. Bellinger
@ 2015-02-02  8:15 ` Christoph Hellwig
  2015-02-03  0:22   ` Nicholas A. Bellinger
  8 siblings, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2015-02-02  8:15 UTC (permalink / raw)
  To: Nicholas A. Bellinger
  Cc: target-devel, linux-scsi, kvm-devel, Paolo Bonzini,
	Michael S. Tsirkin, Nicholas Bellinger, Al Viro

Hi Nic,

Al has been rewriting the vhost code to use iov_iter primitives,
can you please rebase it on top of that istead of using the obsolete
infrastructure?

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

* Re: [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support
  2015-02-02  8:15 ` [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Christoph Hellwig
@ 2015-02-03  0:22   ` Nicholas A. Bellinger
  0 siblings, 0 replies; 15+ messages in thread
From: Nicholas A. Bellinger @ 2015-02-03  0:22 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Nicholas A. Bellinger, target-devel, linux-scsi, kvm-devel,
	Paolo Bonzini, Michael S. Tsirkin, Al Viro

On Mon, 2015-02-02 at 00:15 -0800, Christoph Hellwig wrote:
> Hi Nic,
> 
> Al has been rewriting the vhost code to use iov_iter primitives,
> can you please rebase it on top of that istead of using the obsolete
> infrastructure?
> 

Yep, already done with the copy_[from,to]_iter() conversion in
vhost_scsi_handle_vqal() + vhost_scsi_complete_cmd_work() respectively.

Looking at iov_iter_get_pages() now to see if it can replace the other
code, or if that should be a post merge improvement instead.

--nab

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

end of thread, other threads:[~2015-02-03  0:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-30  8:12 [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 1/8] lib/iovec: Add memcpy_fromiovec_out library function Nicholas A. Bellinger
2015-01-30  9:33   ` Paolo Bonzini
2015-02-01  7:15     ` Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 2/8] vhost/scsi: Convert completion path to use memcpy_toiovecend Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 3/8] vhost/scsi: Fix incorrect early vhost_scsi_handle_vq failures Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 4/8] vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len Nicholas A. Bellinger
2015-01-30 10:51   ` Michael S. Tsirkin
2015-02-01  7:24     ` Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 5/8] vhost/scsi: Add common vhost_scsi_queue_desc code Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 6/8] vhost/scsi: Add ANY_LAYOUT prerequisites Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 7/8] vhost/scsi: Add ANY_LAYOUT support Nicholas A. Bellinger
2015-01-30  8:12 ` [PATCH 8/8] vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits Nicholas A. Bellinger
2015-02-02  8:15 ` [PATCH 0/8] vhost/scsi: Add ANY_LAYOUT support Christoph Hellwig
2015-02-03  0:22   ` Nicholas A. Bellinger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.