From: "Michael S. Tsirkin" <mst@redhat.com>
To: "Nicholas A. Bellinger" <nab@daterainc.com>
Cc: target-devel <target-devel@vger.kernel.org>,
linux-scsi <linux-scsi@vger.kernel.org>,
Paolo Bonzini <pbonzini@redhat.com>,
"Martin K. Petersen" <martin.petersen@oracle.com>,
Sagi Grimberg <sagig@mellanox.com>,
Christoph Hellwig <hch@lst.de>, Hannes Reinecke <hare@suse.de>,
"H. Peter Anvin" <hpa@zytor.com>,
Nicholas Bellinger <nab@linux-iscsi.org>,
Sagi Grimberg <sagig@dev.mellanox.co.il>
Subject: Re: [PATCH-v2 5/6] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping
Date: Mon, 9 Jun 2014 16:15:24 +0300 [thread overview]
Message-ID: <20140609131524.GB5013@redhat.com> (raw)
In-Reply-To: <1400725582-5521-6-git-send-email-nab@daterainc.com>
On Thu, May 22, 2014 at 02:26:21AM +0000, Nicholas A. Bellinger wrote:
> 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.
>
> v4 changes:
> - Add prot_pto=1 in tcm_vhost_submission_work() when no PI buffer
> exists (nab)
> - Get rid of req + cdb pointer casts in vhost_scsi_handle_vq (mst)
> - Ensure that virtio_scsi_cmd_req_pi processing happens regardless
> of data_num in vhost_scsi_handle_vq (nab)
> - Pass TARGET_PROT_ALL into transport_init_session_tags() (nab)
> - Convert vhost_scsi_handle_vq to use memcpy_fromiovecend() (mst)
> - Convert vhost_scsi_handle_vq to use pi_bytesout + pi_bytesin (nab)
>
> v3 changes:
> - Use feature_bit for determining virtio-scsi header type (Paolo)
>
> 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 | 183 ++++++++++++++++++++++++++++++++++----------------
> 1 file changed, 124 insertions(+), 59 deletions(-)
>
> diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
> index eabcf18..17ec04b 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
> @@ -720,11 +721,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;
> @@ -756,13 +755,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;
> }
>
> @@ -913,18 +915,17 @@ 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
> + se_cmd->prot_pto = true;
> } else {
> sg_ptr = NULL;
> }
> @@ -935,7 +936,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);
> @@ -967,12 +968,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, prot_bytes;
> + size_t req_size;
> + u16 lun;
> + u8 *target, *lunp, task_attr;
> + bool hdr_pi;
> + void *req, *cdb;
>
> mutex_lock(&vq->mutex);
> /*
> @@ -1003,7 +1010,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;
> @@ -1033,29 +1040,38 @@ 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"
> - " bytes\n", vq->iov[0].iov_len);
> + if (vs->dev.acked_features & VIRTIO_SCSI_F_T10_PI) {
Actually this should use the has_feature macro.
And if you did you would notice that this is wrong:
you are doing & with bit number.
Unfortunately I am reworking that API for the next
kernel, so there's a conflict with bits in
my tree.
How about you rebase on top of vhost-next in my tree
and I'll merge it all together?
> + req = &v_req_pi;
> + lunp = &v_req_pi.lun[0];
> + target = &v_req_pi.lun[1];
> + req_size = sizeof(v_req_pi);
> + hdr_pi = true;
> + } else {
> + req = &v_req;
> + lunp = &v_req.lun[0];
> + target = &v_req.lun[1];
> + req_size = sizeof(v_req);
> + hdr_pi = false;
> + }
> +
> + 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;
> }
> - 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));
> + ret = memcpy_fromiovecend(req, &vq->iov[0], 0, req_size);
> if (unlikely(ret)) {
> vq_err(vq, "Faulted on virtio_scsi_cmd_req\n");
> break;
> }
>
> /* virtio-scsi spec requires byte 0 of the lun to be 1 */
> - if (unlikely(v_req.lun[0] != 1)) {
> + if (unlikely(*lunp != 1)) {
> vhost_scsi_send_bad_target(vs, vq, head, out);
> continue;
> }
>
> - /* 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)) {
> @@ -1063,17 +1079,78 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
> continue;
> }
>
> + data_niov = data_num;
> + prot_niov = prot_first = prot_bytes = 0;
> + /*
> + * Determine if any protection information iovecs are preceeding
> + * the actual data payload, and adjust data_first + data_niov
> + * values accordingly for vhost_scsi_map_iov_to_sgl() below.
> + *
> + * Also extract virtio_scsi header bits for vhost_scsi_get_tag()
> + */
> + if (hdr_pi) {
> + 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");
> + goto err_cmd;
> + }
> + prot_bytes = 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;
> + }
> + prot_bytes = v_req_pi.pi_bytesin;
> + }
> + if (prot_bytes) {
> + int tmp = 0;
> +
> + for (i = 0; i < data_num; i++) {
> + tmp += vq->iov[data_first + i].iov_len;
> + prot_niov++;
> + if (tmp >= prot_bytes)
> + break;
> + }
> + prot_first = data_first;
> + data_first += prot_niov;
> + data_niov = data_num - 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);
>
> @@ -1081,40 +1158,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
> @@ -1788,7 +1853,7 @@ static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tpg,
> tv_nexus->tvn_se_sess = transport_init_session_tags(
> TCM_VHOST_DEFAULT_TAGS,
> sizeof(struct tcm_vhost_cmd),
> - TARGET_PROT_NORMAL);
> + TARGET_PROT_ALL);
> if (IS_ERR(tv_nexus->tvn_se_sess)) {
> mutex_unlock(&tpg->tv_tpg_mutex);
> kfree(tv_nexus);
> --
> 1.7.10.4
next prev parent reply other threads:[~2014-06-09 13:15 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-22 2:26 [PATCH-v2 0/6] vhost/scsi: Add T10 PI SGL passthrough support Nicholas A. Bellinger
2014-05-22 2:26 ` [PATCH-v2 1/6] virtio-scsi.h: Add virtio_scsi_cmd_req_pi + VIRTIO_SCSI_F_T10_PI bits Nicholas A. Bellinger
2014-05-22 6:57 ` Michael S. Tsirkin
2014-05-22 11:00 ` Rusty Russell
2014-05-22 20:38 ` Nicholas A. Bellinger
2014-06-09 13:16 ` Michael S. Tsirkin
2014-05-22 2:26 ` [PATCH-v2 2/6] vhost/scsi: Move sanity check into vhost_scsi_map_iov_to_sgl Nicholas A. Bellinger
2014-05-22 2:26 ` [PATCH-v2 3/6] vhost/scsi: Add preallocation of protection SGLs Nicholas A. Bellinger
2014-05-22 2:26 ` [PATCH-v2 4/6] vhost/scsi: Add T10 PI IOV -> SGL memory mapping logic Nicholas A. Bellinger
2014-05-22 2:26 ` [PATCH-v2 5/6] vhost/scsi: Enable T10 PI IOV -> SGL memory mapping Nicholas A. Bellinger
2014-06-09 13:15 ` Michael S. Tsirkin [this message]
2014-05-22 2:26 ` [PATCH-v2 6/6] virtio-scsi: Enable DIF/DIX modes in SCSI host LLD Nicholas A. Bellinger
2014-05-22 8:37 ` Paolo Bonzini
2014-05-22 20:41 ` Nicholas A. Bellinger
2014-05-22 8:37 ` [PATCH-v2 0/6] vhost/scsi: Add T10 PI SGL passthrough support Paolo Bonzini
2014-06-02 7:31 ` Michael S. Tsirkin
2014-06-08 16:05 ` Michael S. Tsirkin
2014-06-09 9:06 ` Paolo Bonzini
2014-06-10 7:07 ` Nicholas A. Bellinger
2014-06-10 8:03 ` Paolo Bonzini
2014-06-09 13:30 ` Michael S. Tsirkin
2014-06-10 7:05 ` Nicholas A. Bellinger
2014-06-10 9:42 ` Michael S. Tsirkin
2014-06-10 11:52 ` Stephen Rothwell
2014-06-10 13:02 ` Michael S. Tsirkin
2014-06-10 15:47 ` Stephen Rothwell
2014-06-10 17:39 ` Nicholas A. Bellinger
2014-06-10 18:45 ` Michael S. Tsirkin
2014-06-10 19:57 ` Nicholas A. Bellinger
2014-06-10 20:09 ` James Bottomley
2014-06-10 20:25 ` Nicholas A. Bellinger
2014-06-10 20:56 ` Linus Torvalds
2014-06-10 21:20 ` Nicholas A. Bellinger
2014-06-11 8:04 ` Michael S. Tsirkin
2014-06-10 19:35 ` Michael S. Tsirkin
2014-06-10 19:53 ` Nicholas A. Bellinger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140609131524.GB5013@redhat.com \
--to=mst@redhat.com \
--cc=hare@suse.de \
--cc=hch@lst.de \
--cc=hpa@zytor.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=nab@daterainc.com \
--cc=nab@linux-iscsi.org \
--cc=pbonzini@redhat.com \
--cc=sagig@dev.mellanox.co.il \
--cc=sagig@mellanox.com \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).