diff options
-rw-r--r-- | drivers/target/target_core_pscsi.c | 9 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 15 | ||||
-rw-r--r-- | drivers/target/tcm_fc/tcm_fc.h | 1 | ||||
-rw-r--r-- | drivers/target/tcm_fc/tfc_cmd.c | 8 | ||||
-rw-r--r-- | drivers/target/tcm_fc/tfc_sess.c | 4 | ||||
-rw-r--r-- | drivers/vhost/tcm_vhost.c | 203 | ||||
-rw-r--r-- | drivers/vhost/tcm_vhost.h | 12 | ||||
-rw-r--r-- | include/target/target_core_base.h | 2 |
8 files changed, 146 insertions, 108 deletions
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 6e32ff6f2fa0..5552fa7426bc 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
@@ -673,8 +673,15 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg) | |||
673 | struct scsi_device *sd = pdv->pdv_sd; | 673 | struct scsi_device *sd = pdv->pdv_sd; |
674 | int result; | 674 | int result; |
675 | struct pscsi_plugin_task *pt = cmd->priv; | 675 | struct pscsi_plugin_task *pt = cmd->priv; |
676 | unsigned char *cdb = &pt->pscsi_cdb[0]; | 676 | unsigned char *cdb; |
677 | /* | ||
678 | * Special case for REPORT_LUNs handling where pscsi_plugin_task has | ||
679 | * not been allocated because TCM is handling the emulation directly. | ||
680 | */ | ||
681 | if (!pt) | ||
682 | return 0; | ||
677 | 683 | ||
684 | cdb = &pt->pscsi_cdb[0]; | ||
678 | result = pt->pscsi_result; | 685 | result = pt->pscsi_result; |
679 | /* | 686 | /* |
680 | * Hack to make sure that Write-Protect modepage is set if R/O mode is | 687 | * Hack to make sure that Write-Protect modepage is set if R/O mode is |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 0eaae23d12b5..4de3186dc44e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -1165,8 +1165,6 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size) | |||
1165 | " 0x%02x\n", cmd->se_tfo->get_fabric_name(), | 1165 | " 0x%02x\n", cmd->se_tfo->get_fabric_name(), |
1166 | cmd->data_length, size, cmd->t_task_cdb[0]); | 1166 | cmd->data_length, size, cmd->t_task_cdb[0]); |
1167 | 1167 | ||
1168 | cmd->cmd_spdtl = size; | ||
1169 | |||
1170 | if (cmd->data_direction == DMA_TO_DEVICE) { | 1168 | if (cmd->data_direction == DMA_TO_DEVICE) { |
1171 | pr_err("Rejecting underflow/overflow" | 1169 | pr_err("Rejecting underflow/overflow" |
1172 | " WRITE data\n"); | 1170 | " WRITE data\n"); |
@@ -2294,9 +2292,9 @@ transport_generic_get_mem(struct se_cmd *cmd) | |||
2294 | return 0; | 2292 | return 0; |
2295 | 2293 | ||
2296 | out: | 2294 | out: |
2297 | while (i >= 0) { | 2295 | while (i > 0) { |
2298 | __free_page(sg_page(&cmd->t_data_sg[i])); | ||
2299 | i--; | 2296 | i--; |
2297 | __free_page(sg_page(&cmd->t_data_sg[i])); | ||
2300 | } | 2298 | } |
2301 | kfree(cmd->t_data_sg); | 2299 | kfree(cmd->t_data_sg); |
2302 | cmd->t_data_sg = NULL; | 2300 | cmd->t_data_sg = NULL; |
@@ -2323,9 +2321,12 @@ int transport_generic_new_cmd(struct se_cmd *cmd) | |||
2323 | if (ret < 0) | 2321 | if (ret < 0) |
2324 | goto out_fail; | 2322 | goto out_fail; |
2325 | } | 2323 | } |
2326 | 2324 | /* | |
2327 | /* Workaround for handling zero-length control CDBs */ | 2325 | * If this command doesn't have any payload and we don't have to call |
2328 | if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) { | 2326 | * into the fabric for data transfers, go ahead and complete it right |
2327 | * away. | ||
2328 | */ | ||
2329 | if (!cmd->data_length) { | ||
2329 | spin_lock_irq(&cmd->t_state_lock); | 2330 | spin_lock_irq(&cmd->t_state_lock); |
2330 | cmd->t_state = TRANSPORT_COMPLETE; | 2331 | cmd->t_state = TRANSPORT_COMPLETE; |
2331 | cmd->transport_state |= CMD_T_ACTIVE; | 2332 | cmd->transport_state |= CMD_T_ACTIVE; |
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index c5eb3c33c3db..eea69358ced3 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h | |||
@@ -131,6 +131,7 @@ extern struct list_head ft_lport_list; | |||
131 | extern struct mutex ft_lport_lock; | 131 | extern struct mutex ft_lport_lock; |
132 | extern struct fc4_prov ft_prov; | 132 | extern struct fc4_prov ft_prov; |
133 | extern struct target_fabric_configfs *ft_configfs; | 133 | extern struct target_fabric_configfs *ft_configfs; |
134 | extern unsigned int ft_debug_logging; | ||
134 | 135 | ||
135 | /* | 136 | /* |
136 | * Fabric methods. | 137 | * Fabric methods. |
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index b9cb5006177e..823e6922249d 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c | |||
@@ -48,7 +48,7 @@ | |||
48 | /* | 48 | /* |
49 | * Dump cmd state for debugging. | 49 | * Dump cmd state for debugging. |
50 | */ | 50 | */ |
51 | void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | 51 | static void _ft_dump_cmd(struct ft_cmd *cmd, const char *caller) |
52 | { | 52 | { |
53 | struct fc_exch *ep; | 53 | struct fc_exch *ep; |
54 | struct fc_seq *sp; | 54 | struct fc_seq *sp; |
@@ -80,6 +80,12 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | |||
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) | ||
84 | { | ||
85 | if (unlikely(ft_debug_logging)) | ||
86 | _ft_dump_cmd(cmd, caller); | ||
87 | } | ||
88 | |||
83 | static void ft_free_cmd(struct ft_cmd *cmd) | 89 | static void ft_free_cmd(struct ft_cmd *cmd) |
84 | { | 90 | { |
85 | struct fc_frame *fp; | 91 | struct fc_frame *fp; |
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 87901fa74dd7..3c9e5b57caab 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c | |||
@@ -456,7 +456,9 @@ static void ft_prlo(struct fc_rport_priv *rdata) | |||
456 | struct ft_tport *tport; | 456 | struct ft_tport *tport; |
457 | 457 | ||
458 | mutex_lock(&ft_lport_lock); | 458 | mutex_lock(&ft_lport_lock); |
459 | tport = rcu_dereference(rdata->local_port->prov[FC_TYPE_FCP]); | 459 | tport = rcu_dereference_protected(rdata->local_port->prov[FC_TYPE_FCP], |
460 | lockdep_is_held(&ft_lport_lock)); | ||
461 | |||
460 | if (!tport) { | 462 | if (!tport) { |
461 | mutex_unlock(&ft_lport_lock); | 463 | mutex_unlock(&ft_lport_lock); |
462 | return; | 464 | return; |
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index fb366540ed54..ed8e2e6c8df2 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c | |||
@@ -53,9 +53,14 @@ | |||
53 | #include "vhost.h" | 53 | #include "vhost.h" |
54 | #include "tcm_vhost.h" | 54 | #include "tcm_vhost.h" |
55 | 55 | ||
56 | enum { | ||
57 | VHOST_SCSI_VQ_CTL = 0, | ||
58 | VHOST_SCSI_VQ_EVT = 1, | ||
59 | VHOST_SCSI_VQ_IO = 2, | ||
60 | }; | ||
61 | |||
56 | struct vhost_scsi { | 62 | struct vhost_scsi { |
57 | atomic_t vhost_ref_cnt; | 63 | struct tcm_vhost_tpg *vs_tpg; /* Protected by vhost_scsi->dev.mutex */ |
58 | struct tcm_vhost_tpg *vs_tpg; | ||
59 | struct vhost_dev dev; | 64 | struct vhost_dev dev; |
60 | struct vhost_virtqueue vqs[3]; | 65 | struct vhost_virtqueue vqs[3]; |
61 | 66 | ||
@@ -131,8 +136,7 @@ static u32 tcm_vhost_get_default_depth(struct se_portal_group *se_tpg) | |||
131 | return 1; | 136 | return 1; |
132 | } | 137 | } |
133 | 138 | ||
134 | static u32 tcm_vhost_get_pr_transport_id( | 139 | static u32 tcm_vhost_get_pr_transport_id(struct se_portal_group *se_tpg, |
135 | struct se_portal_group *se_tpg, | ||
136 | struct se_node_acl *se_nacl, | 140 | struct se_node_acl *se_nacl, |
137 | struct t10_pr_registration *pr_reg, | 141 | struct t10_pr_registration *pr_reg, |
138 | int *format_code, | 142 | int *format_code, |
@@ -162,8 +166,7 @@ static u32 tcm_vhost_get_pr_transport_id( | |||
162 | format_code, buf); | 166 | format_code, buf); |
163 | } | 167 | } |
164 | 168 | ||
165 | static u32 tcm_vhost_get_pr_transport_id_len( | 169 | static u32 tcm_vhost_get_pr_transport_id_len(struct se_portal_group *se_tpg, |
166 | struct se_portal_group *se_tpg, | ||
167 | struct se_node_acl *se_nacl, | 170 | struct se_node_acl *se_nacl, |
168 | struct t10_pr_registration *pr_reg, | 171 | struct t10_pr_registration *pr_reg, |
169 | int *format_code) | 172 | int *format_code) |
@@ -192,8 +195,7 @@ static u32 tcm_vhost_get_pr_transport_id_len( | |||
192 | format_code); | 195 | format_code); |
193 | } | 196 | } |
194 | 197 | ||
195 | static char *tcm_vhost_parse_pr_out_transport_id( | 198 | static char *tcm_vhost_parse_pr_out_transport_id(struct se_portal_group *se_tpg, |
196 | struct se_portal_group *se_tpg, | ||
197 | const char *buf, | 199 | const char *buf, |
198 | u32 *out_tid_len, | 200 | u32 *out_tid_len, |
199 | char **port_nexus_ptr) | 201 | char **port_nexus_ptr) |
@@ -236,8 +238,7 @@ static struct se_node_acl *tcm_vhost_alloc_fabric_acl( | |||
236 | return &nacl->se_node_acl; | 238 | return &nacl->se_node_acl; |
237 | } | 239 | } |
238 | 240 | ||
239 | static void tcm_vhost_release_fabric_acl( | 241 | static void tcm_vhost_release_fabric_acl(struct se_portal_group *se_tpg, |
240 | struct se_portal_group *se_tpg, | ||
241 | struct se_node_acl *se_nacl) | 242 | struct se_node_acl *se_nacl) |
242 | { | 243 | { |
243 | struct tcm_vhost_nacl *nacl = container_of(se_nacl, | 244 | struct tcm_vhost_nacl *nacl = container_of(se_nacl, |
@@ -297,7 +298,16 @@ static int tcm_vhost_get_cmd_state(struct se_cmd *se_cmd) | |||
297 | return 0; | 298 | return 0; |
298 | } | 299 | } |
299 | 300 | ||
300 | static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *); | 301 | static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) |
302 | { | ||
303 | struct vhost_scsi *vs = tv_cmd->tvc_vhost; | ||
304 | |||
305 | spin_lock_bh(&vs->vs_completion_lock); | ||
306 | list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); | ||
307 | spin_unlock_bh(&vs->vs_completion_lock); | ||
308 | |||
309 | vhost_work_queue(&vs->dev, &vs->vs_completion_work); | ||
310 | } | ||
301 | 311 | ||
302 | static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) | 312 | static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) |
303 | { | 313 | { |
@@ -381,7 +391,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) | |||
381 | vs_completion_work); | 391 | vs_completion_work); |
382 | struct tcm_vhost_cmd *tv_cmd; | 392 | struct tcm_vhost_cmd *tv_cmd; |
383 | 393 | ||
384 | while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs)) != NULL) { | 394 | while ((tv_cmd = vhost_scsi_get_cmd_from_completion(vs))) { |
385 | struct virtio_scsi_cmd_resp v_rsp; | 395 | struct virtio_scsi_cmd_resp v_rsp; |
386 | struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; | 396 | struct se_cmd *se_cmd = &tv_cmd->tvc_se_cmd; |
387 | int ret; | 397 | int ret; |
@@ -408,19 +418,6 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work) | |||
408 | vhost_signal(&vs->dev, &vs->vqs[2]); | 418 | vhost_signal(&vs->dev, &vs->vqs[2]); |
409 | } | 419 | } |
410 | 420 | ||
411 | static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *tv_cmd) | ||
412 | { | ||
413 | struct vhost_scsi *vs = tv_cmd->tvc_vhost; | ||
414 | |||
415 | pr_debug("%s tv_cmd %p\n", __func__, tv_cmd); | ||
416 | |||
417 | spin_lock_bh(&vs->vs_completion_lock); | ||
418 | list_add_tail(&tv_cmd->tvc_completion_list, &vs->vs_completion_list); | ||
419 | spin_unlock_bh(&vs->vs_completion_lock); | ||
420 | |||
421 | vhost_work_queue(&vs->dev, &vs->vs_completion_work); | ||
422 | } | ||
423 | |||
424 | static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( | 421 | static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( |
425 | struct tcm_vhost_tpg *tv_tpg, | 422 | struct tcm_vhost_tpg *tv_tpg, |
426 | struct virtio_scsi_cmd_req *v_req, | 423 | struct virtio_scsi_cmd_req *v_req, |
@@ -533,8 +530,8 @@ static int vhost_scsi_map_iov_to_sgl(struct tcm_vhost_cmd *tv_cmd, | |||
533 | sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); | 530 | sg = kmalloc(sizeof(tv_cmd->tvc_sgl[0]) * sgl_count, GFP_ATOMIC); |
534 | if (!sg) | 531 | if (!sg) |
535 | return -ENOMEM; | 532 | return -ENOMEM; |
536 | pr_debug("%s sg %p sgl_count %u is_err %ld\n", __func__, | 533 | pr_debug("%s sg %p sgl_count %u is_err %d\n", __func__, |
537 | sg, sgl_count, IS_ERR(sg)); | 534 | sg, sgl_count, !sg); |
538 | sg_init_table(sg, sgl_count); | 535 | sg_init_table(sg, sgl_count); |
539 | 536 | ||
540 | tv_cmd->tvc_sgl = sg; | 537 | tv_cmd->tvc_sgl = sg; |
@@ -787,12 +784,12 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs) | |||
787 | 784 | ||
788 | static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) | 785 | static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) |
789 | { | 786 | { |
790 | pr_err("%s: The handling func for control queue.\n", __func__); | 787 | pr_debug("%s: The handling func for control queue.\n", __func__); |
791 | } | 788 | } |
792 | 789 | ||
793 | static void vhost_scsi_evt_handle_kick(struct vhost_work *work) | 790 | static void vhost_scsi_evt_handle_kick(struct vhost_work *work) |
794 | { | 791 | { |
795 | pr_err("%s: The handling func for event queue.\n", __func__); | 792 | pr_debug("%s: The handling func for event queue.\n", __func__); |
796 | } | 793 | } |
797 | 794 | ||
798 | static void vhost_scsi_handle_kick(struct vhost_work *work) | 795 | static void vhost_scsi_handle_kick(struct vhost_work *work) |
@@ -825,11 +822,6 @@ static int vhost_scsi_set_endpoint( | |||
825 | return -EFAULT; | 822 | return -EFAULT; |
826 | } | 823 | } |
827 | } | 824 | } |
828 | |||
829 | if (vs->vs_tpg) { | ||
830 | mutex_unlock(&vs->dev.mutex); | ||
831 | return -EEXIST; | ||
832 | } | ||
833 | mutex_unlock(&vs->dev.mutex); | 825 | mutex_unlock(&vs->dev.mutex); |
834 | 826 | ||
835 | mutex_lock(&tcm_vhost_mutex); | 827 | mutex_lock(&tcm_vhost_mutex); |
@@ -839,7 +831,7 @@ static int vhost_scsi_set_endpoint( | |||
839 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | 831 | mutex_unlock(&tv_tpg->tv_tpg_mutex); |
840 | continue; | 832 | continue; |
841 | } | 833 | } |
842 | if (atomic_read(&tv_tpg->tv_tpg_vhost_count)) { | 834 | if (tv_tpg->tv_tpg_vhost_count != 0) { |
843 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | 835 | mutex_unlock(&tv_tpg->tv_tpg_mutex); |
844 | continue; | 836 | continue; |
845 | } | 837 | } |
@@ -847,14 +839,20 @@ static int vhost_scsi_set_endpoint( | |||
847 | 839 | ||
848 | if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) && | 840 | if (!strcmp(tv_tport->tport_name, t->vhost_wwpn) && |
849 | (tv_tpg->tport_tpgt == t->vhost_tpgt)) { | 841 | (tv_tpg->tport_tpgt == t->vhost_tpgt)) { |
850 | atomic_inc(&tv_tpg->tv_tpg_vhost_count); | 842 | tv_tpg->tv_tpg_vhost_count++; |
851 | smp_mb__after_atomic_inc(); | ||
852 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | 843 | mutex_unlock(&tv_tpg->tv_tpg_mutex); |
853 | mutex_unlock(&tcm_vhost_mutex); | 844 | mutex_unlock(&tcm_vhost_mutex); |
854 | 845 | ||
855 | mutex_lock(&vs->dev.mutex); | 846 | mutex_lock(&vs->dev.mutex); |
847 | if (vs->vs_tpg) { | ||
848 | mutex_unlock(&vs->dev.mutex); | ||
849 | mutex_lock(&tv_tpg->tv_tpg_mutex); | ||
850 | tv_tpg->tv_tpg_vhost_count--; | ||
851 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | ||
852 | return -EEXIST; | ||
853 | } | ||
854 | |||
856 | vs->vs_tpg = tv_tpg; | 855 | vs->vs_tpg = tv_tpg; |
857 | atomic_inc(&vs->vhost_ref_cnt); | ||
858 | smp_mb__after_atomic_inc(); | 856 | smp_mb__after_atomic_inc(); |
859 | mutex_unlock(&vs->dev.mutex); | 857 | mutex_unlock(&vs->dev.mutex); |
860 | return 0; | 858 | return 0; |
@@ -871,38 +869,42 @@ static int vhost_scsi_clear_endpoint( | |||
871 | { | 869 | { |
872 | struct tcm_vhost_tport *tv_tport; | 870 | struct tcm_vhost_tport *tv_tport; |
873 | struct tcm_vhost_tpg *tv_tpg; | 871 | struct tcm_vhost_tpg *tv_tpg; |
874 | int index; | 872 | int index, ret; |
875 | 873 | ||
876 | mutex_lock(&vs->dev.mutex); | 874 | mutex_lock(&vs->dev.mutex); |
877 | /* Verify that ring has been setup correctly. */ | 875 | /* Verify that ring has been setup correctly. */ |
878 | for (index = 0; index < vs->dev.nvqs; ++index) { | 876 | for (index = 0; index < vs->dev.nvqs; ++index) { |
879 | if (!vhost_vq_access_ok(&vs->vqs[index])) { | 877 | if (!vhost_vq_access_ok(&vs->vqs[index])) { |
880 | mutex_unlock(&vs->dev.mutex); | 878 | ret = -EFAULT; |
881 | return -EFAULT; | 879 | goto err; |
882 | } | 880 | } |
883 | } | 881 | } |
884 | 882 | ||
885 | if (!vs->vs_tpg) { | 883 | if (!vs->vs_tpg) { |
886 | mutex_unlock(&vs->dev.mutex); | 884 | ret = -ENODEV; |
887 | return -ENODEV; | 885 | goto err; |
888 | } | 886 | } |
889 | tv_tpg = vs->vs_tpg; | 887 | tv_tpg = vs->vs_tpg; |
890 | tv_tport = tv_tpg->tport; | 888 | tv_tport = tv_tpg->tport; |
891 | 889 | ||
892 | if (strcmp(tv_tport->tport_name, t->vhost_wwpn) || | 890 | if (strcmp(tv_tport->tport_name, t->vhost_wwpn) || |
893 | (tv_tpg->tport_tpgt != t->vhost_tpgt)) { | 891 | (tv_tpg->tport_tpgt != t->vhost_tpgt)) { |
894 | mutex_unlock(&vs->dev.mutex); | ||
895 | pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" | 892 | pr_warn("tv_tport->tport_name: %s, tv_tpg->tport_tpgt: %hu" |
896 | " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", | 893 | " does not match t->vhost_wwpn: %s, t->vhost_tpgt: %hu\n", |
897 | tv_tport->tport_name, tv_tpg->tport_tpgt, | 894 | tv_tport->tport_name, tv_tpg->tport_tpgt, |
898 | t->vhost_wwpn, t->vhost_tpgt); | 895 | t->vhost_wwpn, t->vhost_tpgt); |
899 | return -EINVAL; | 896 | ret = -EINVAL; |
897 | goto err; | ||
900 | } | 898 | } |
901 | atomic_dec(&tv_tpg->tv_tpg_vhost_count); | 899 | tv_tpg->tv_tpg_vhost_count--; |
902 | vs->vs_tpg = NULL; | 900 | vs->vs_tpg = NULL; |
903 | mutex_unlock(&vs->dev.mutex); | 901 | mutex_unlock(&vs->dev.mutex); |
904 | 902 | ||
905 | return 0; | 903 | return 0; |
904 | |||
905 | err: | ||
906 | mutex_unlock(&vs->dev.mutex); | ||
907 | return ret; | ||
906 | } | 908 | } |
907 | 909 | ||
908 | static int vhost_scsi_open(struct inode *inode, struct file *f) | 910 | static int vhost_scsi_open(struct inode *inode, struct file *f) |
@@ -918,9 +920,9 @@ static int vhost_scsi_open(struct inode *inode, struct file *f) | |||
918 | INIT_LIST_HEAD(&s->vs_completion_list); | 920 | INIT_LIST_HEAD(&s->vs_completion_list); |
919 | spin_lock_init(&s->vs_completion_lock); | 921 | spin_lock_init(&s->vs_completion_lock); |
920 | 922 | ||
921 | s->vqs[0].handle_kick = vhost_scsi_ctl_handle_kick; | 923 | s->vqs[VHOST_SCSI_VQ_CTL].handle_kick = vhost_scsi_ctl_handle_kick; |
922 | s->vqs[1].handle_kick = vhost_scsi_evt_handle_kick; | 924 | s->vqs[VHOST_SCSI_VQ_EVT].handle_kick = vhost_scsi_evt_handle_kick; |
923 | s->vqs[2].handle_kick = vhost_scsi_handle_kick; | 925 | s->vqs[VHOST_SCSI_VQ_IO].handle_kick = vhost_scsi_handle_kick; |
924 | r = vhost_dev_init(&s->dev, s->vqs, 3); | 926 | r = vhost_dev_init(&s->dev, s->vqs, 3); |
925 | if (r < 0) { | 927 | if (r < 0) { |
926 | kfree(s); | 928 | kfree(s); |
@@ -949,6 +951,18 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) | |||
949 | return 0; | 951 | return 0; |
950 | } | 952 | } |
951 | 953 | ||
954 | static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index) | ||
955 | { | ||
956 | vhost_poll_flush(&vs->dev.vqs[index].poll); | ||
957 | } | ||
958 | |||
959 | static void vhost_scsi_flush(struct vhost_scsi *vs) | ||
960 | { | ||
961 | vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_CTL); | ||
962 | vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_EVT); | ||
963 | vhost_scsi_flush_vq(vs, VHOST_SCSI_VQ_IO); | ||
964 | } | ||
965 | |||
952 | static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) | 966 | static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) |
953 | { | 967 | { |
954 | if (features & ~VHOST_FEATURES) | 968 | if (features & ~VHOST_FEATURES) |
@@ -961,7 +975,8 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) | |||
961 | return -EFAULT; | 975 | return -EFAULT; |
962 | } | 976 | } |
963 | vs->dev.acked_features = features; | 977 | vs->dev.acked_features = features; |
964 | /* TODO possibly smp_wmb() and flush vqs */ | 978 | smp_wmb(); |
979 | vhost_scsi_flush(vs); | ||
965 | mutex_unlock(&vs->dev.mutex); | 980 | mutex_unlock(&vs->dev.mutex); |
966 | return 0; | 981 | return 0; |
967 | } | 982 | } |
@@ -974,26 +989,25 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, | |||
974 | void __user *argp = (void __user *)arg; | 989 | void __user *argp = (void __user *)arg; |
975 | u64 __user *featurep = argp; | 990 | u64 __user *featurep = argp; |
976 | u64 features; | 991 | u64 features; |
977 | int r; | 992 | int r, abi_version = VHOST_SCSI_ABI_VERSION; |
978 | 993 | ||
979 | switch (ioctl) { | 994 | switch (ioctl) { |
980 | case VHOST_SCSI_SET_ENDPOINT: | 995 | case VHOST_SCSI_SET_ENDPOINT: |
981 | if (copy_from_user(&backend, argp, sizeof backend)) | 996 | if (copy_from_user(&backend, argp, sizeof backend)) |
982 | return -EFAULT; | 997 | return -EFAULT; |
998 | if (backend.reserved != 0) | ||
999 | return -EOPNOTSUPP; | ||
983 | 1000 | ||
984 | return vhost_scsi_set_endpoint(vs, &backend); | 1001 | return vhost_scsi_set_endpoint(vs, &backend); |
985 | case VHOST_SCSI_CLEAR_ENDPOINT: | 1002 | case VHOST_SCSI_CLEAR_ENDPOINT: |
986 | if (copy_from_user(&backend, argp, sizeof backend)) | 1003 | if (copy_from_user(&backend, argp, sizeof backend)) |
987 | return -EFAULT; | 1004 | return -EFAULT; |
1005 | if (backend.reserved != 0) | ||
1006 | return -EOPNOTSUPP; | ||
988 | 1007 | ||
989 | return vhost_scsi_clear_endpoint(vs, &backend); | 1008 | return vhost_scsi_clear_endpoint(vs, &backend); |
990 | case VHOST_SCSI_GET_ABI_VERSION: | 1009 | case VHOST_SCSI_GET_ABI_VERSION: |
991 | if (copy_from_user(&backend, argp, sizeof backend)) | 1010 | if (copy_to_user(argp, &abi_version, sizeof abi_version)) |
992 | return -EFAULT; | ||
993 | |||
994 | backend.abi_version = VHOST_SCSI_ABI_VERSION; | ||
995 | |||
996 | if (copy_to_user(argp, &backend, sizeof backend)) | ||
997 | return -EFAULT; | 1011 | return -EFAULT; |
998 | return 0; | 1012 | return 0; |
999 | case VHOST_GET_FEATURES: | 1013 | case VHOST_GET_FEATURES: |
@@ -1013,11 +1027,21 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, | |||
1013 | } | 1027 | } |
1014 | } | 1028 | } |
1015 | 1029 | ||
1030 | #ifdef CONFIG_COMPAT | ||
1031 | static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl, | ||
1032 | unsigned long arg) | ||
1033 | { | ||
1034 | return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg)); | ||
1035 | } | ||
1036 | #endif | ||
1037 | |||
1016 | static const struct file_operations vhost_scsi_fops = { | 1038 | static const struct file_operations vhost_scsi_fops = { |
1017 | .owner = THIS_MODULE, | 1039 | .owner = THIS_MODULE, |
1018 | .release = vhost_scsi_release, | 1040 | .release = vhost_scsi_release, |
1019 | .unlocked_ioctl = vhost_scsi_ioctl, | 1041 | .unlocked_ioctl = vhost_scsi_ioctl, |
1020 | /* TODO compat ioctl? */ | 1042 | #ifdef CONFIG_COMPAT |
1043 | .compat_ioctl = vhost_scsi_compat_ioctl, | ||
1044 | #endif | ||
1021 | .open = vhost_scsi_open, | 1045 | .open = vhost_scsi_open, |
1022 | .llseek = noop_llseek, | 1046 | .llseek = noop_llseek, |
1023 | }; | 1047 | }; |
@@ -1054,28 +1078,28 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport) | |||
1054 | return "Unknown"; | 1078 | return "Unknown"; |
1055 | } | 1079 | } |
1056 | 1080 | ||
1057 | static int tcm_vhost_port_link( | 1081 | static int tcm_vhost_port_link(struct se_portal_group *se_tpg, |
1058 | struct se_portal_group *se_tpg, | ||
1059 | struct se_lun *lun) | 1082 | struct se_lun *lun) |
1060 | { | 1083 | { |
1061 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, | 1084 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, |
1062 | struct tcm_vhost_tpg, se_tpg); | 1085 | struct tcm_vhost_tpg, se_tpg); |
1063 | 1086 | ||
1064 | atomic_inc(&tv_tpg->tv_tpg_port_count); | 1087 | mutex_lock(&tv_tpg->tv_tpg_mutex); |
1065 | smp_mb__after_atomic_inc(); | 1088 | tv_tpg->tv_tpg_port_count++; |
1089 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | ||
1066 | 1090 | ||
1067 | return 0; | 1091 | return 0; |
1068 | } | 1092 | } |
1069 | 1093 | ||
1070 | static void tcm_vhost_port_unlink( | 1094 | static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg, |
1071 | struct se_portal_group *se_tpg, | ||
1072 | struct se_lun *se_lun) | 1095 | struct se_lun *se_lun) |
1073 | { | 1096 | { |
1074 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, | 1097 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, |
1075 | struct tcm_vhost_tpg, se_tpg); | 1098 | struct tcm_vhost_tpg, se_tpg); |
1076 | 1099 | ||
1077 | atomic_dec(&tv_tpg->tv_tpg_port_count); | 1100 | mutex_lock(&tv_tpg->tv_tpg_mutex); |
1078 | smp_mb__after_atomic_dec(); | 1101 | tv_tpg->tv_tpg_port_count--; |
1102 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | ||
1079 | } | 1103 | } |
1080 | 1104 | ||
1081 | static struct se_node_acl *tcm_vhost_make_nodeacl( | 1105 | static struct se_node_acl *tcm_vhost_make_nodeacl( |
@@ -1122,8 +1146,7 @@ static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl) | |||
1122 | kfree(nacl); | 1146 | kfree(nacl); |
1123 | } | 1147 | } |
1124 | 1148 | ||
1125 | static int tcm_vhost_make_nexus( | 1149 | static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg, |
1126 | struct tcm_vhost_tpg *tv_tpg, | ||
1127 | const char *name) | 1150 | const char *name) |
1128 | { | 1151 | { |
1129 | struct se_portal_group *se_tpg; | 1152 | struct se_portal_group *se_tpg; |
@@ -1168,7 +1191,7 @@ static int tcm_vhost_make_nexus( | |||
1168 | return -ENOMEM; | 1191 | return -ENOMEM; |
1169 | } | 1192 | } |
1170 | /* | 1193 | /* |
1171 | * Now register the TCM vHost virtual I_T Nexus as active with the | 1194 | * Now register the TCM vhost virtual I_T Nexus as active with the |
1172 | * call to __transport_register_session() | 1195 | * call to __transport_register_session() |
1173 | */ | 1196 | */ |
1174 | __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, | 1197 | __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, |
@@ -1179,8 +1202,7 @@ static int tcm_vhost_make_nexus( | |||
1179 | return 0; | 1202 | return 0; |
1180 | } | 1203 | } |
1181 | 1204 | ||
1182 | static int tcm_vhost_drop_nexus( | 1205 | static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg) |
1183 | struct tcm_vhost_tpg *tpg) | ||
1184 | { | 1206 | { |
1185 | struct se_session *se_sess; | 1207 | struct se_session *se_sess; |
1186 | struct tcm_vhost_nexus *tv_nexus; | 1208 | struct tcm_vhost_nexus *tv_nexus; |
@@ -1198,27 +1220,27 @@ static int tcm_vhost_drop_nexus( | |||
1198 | return -ENODEV; | 1220 | return -ENODEV; |
1199 | } | 1221 | } |
1200 | 1222 | ||
1201 | if (atomic_read(&tpg->tv_tpg_port_count)) { | 1223 | if (tpg->tv_tpg_port_count != 0) { |
1202 | mutex_unlock(&tpg->tv_tpg_mutex); | 1224 | mutex_unlock(&tpg->tv_tpg_mutex); |
1203 | pr_err("Unable to remove TCM_vHost I_T Nexus with" | 1225 | pr_err("Unable to remove TCM_vhost I_T Nexus with" |
1204 | " active TPG port count: %d\n", | 1226 | " active TPG port count: %d\n", |
1205 | atomic_read(&tpg->tv_tpg_port_count)); | 1227 | tpg->tv_tpg_port_count); |
1206 | return -EPERM; | 1228 | return -EBUSY; |
1207 | } | 1229 | } |
1208 | 1230 | ||
1209 | if (atomic_read(&tpg->tv_tpg_vhost_count)) { | 1231 | if (tpg->tv_tpg_vhost_count != 0) { |
1210 | mutex_unlock(&tpg->tv_tpg_mutex); | 1232 | mutex_unlock(&tpg->tv_tpg_mutex); |
1211 | pr_err("Unable to remove TCM_vHost I_T Nexus with" | 1233 | pr_err("Unable to remove TCM_vhost I_T Nexus with" |
1212 | " active TPG vhost count: %d\n", | 1234 | " active TPG vhost count: %d\n", |
1213 | atomic_read(&tpg->tv_tpg_vhost_count)); | 1235 | tpg->tv_tpg_vhost_count); |
1214 | return -EPERM; | 1236 | return -EBUSY; |
1215 | } | 1237 | } |
1216 | 1238 | ||
1217 | pr_debug("TCM_vHost_ConfigFS: Removing I_T Nexus to emulated" | 1239 | pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated" |
1218 | " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), | 1240 | " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), |
1219 | tv_nexus->tvn_se_sess->se_node_acl->initiatorname); | 1241 | tv_nexus->tvn_se_sess->se_node_acl->initiatorname); |
1220 | /* | 1242 | /* |
1221 | * Release the SCSI I_T Nexus to the emulated vHost Target Port | 1243 | * Release the SCSI I_T Nexus to the emulated vhost Target Port |
1222 | */ | 1244 | */ |
1223 | transport_deregister_session(tv_nexus->tvn_se_sess); | 1245 | transport_deregister_session(tv_nexus->tvn_se_sess); |
1224 | tpg->tpg_nexus = NULL; | 1246 | tpg->tpg_nexus = NULL; |
@@ -1228,8 +1250,7 @@ static int tcm_vhost_drop_nexus( | |||
1228 | return 0; | 1250 | return 0; |
1229 | } | 1251 | } |
1230 | 1252 | ||
1231 | static ssize_t tcm_vhost_tpg_show_nexus( | 1253 | static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg, |
1232 | struct se_portal_group *se_tpg, | ||
1233 | char *page) | 1254 | char *page) |
1234 | { | 1255 | { |
1235 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, | 1256 | struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, |
@@ -1250,8 +1271,7 @@ static ssize_t tcm_vhost_tpg_show_nexus( | |||
1250 | return ret; | 1271 | return ret; |
1251 | } | 1272 | } |
1252 | 1273 | ||
1253 | static ssize_t tcm_vhost_tpg_store_nexus( | 1274 | static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg, |
1254 | struct se_portal_group *se_tpg, | ||
1255 | const char *page, | 1275 | const char *page, |
1256 | size_t count) | 1276 | size_t count) |
1257 | { | 1277 | { |
@@ -1336,8 +1356,7 @@ static struct configfs_attribute *tcm_vhost_tpg_attrs[] = { | |||
1336 | NULL, | 1356 | NULL, |
1337 | }; | 1357 | }; |
1338 | 1358 | ||
1339 | static struct se_portal_group *tcm_vhost_make_tpg( | 1359 | static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn, |
1340 | struct se_wwn *wwn, | ||
1341 | struct config_group *group, | 1360 | struct config_group *group, |
1342 | const char *name) | 1361 | const char *name) |
1343 | { | 1362 | { |
@@ -1385,7 +1404,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) | |||
1385 | list_del(&tpg->tv_tpg_list); | 1404 | list_del(&tpg->tv_tpg_list); |
1386 | mutex_unlock(&tcm_vhost_mutex); | 1405 | mutex_unlock(&tcm_vhost_mutex); |
1387 | /* | 1406 | /* |
1388 | * Release the virtual I_T Nexus for this vHost TPG | 1407 | * Release the virtual I_T Nexus for this vhost TPG |
1389 | */ | 1408 | */ |
1390 | tcm_vhost_drop_nexus(tpg); | 1409 | tcm_vhost_drop_nexus(tpg); |
1391 | /* | 1410 | /* |
@@ -1395,8 +1414,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg) | |||
1395 | kfree(tpg); | 1414 | kfree(tpg); |
1396 | } | 1415 | } |
1397 | 1416 | ||
1398 | static struct se_wwn *tcm_vhost_make_tport( | 1417 | static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf, |
1399 | struct target_fabric_configfs *tf, | ||
1400 | struct config_group *group, | 1418 | struct config_group *group, |
1401 | const char *name) | 1419 | const char *name) |
1402 | { | 1420 | { |
@@ -1592,7 +1610,10 @@ static void tcm_vhost_deregister_configfs(void) | |||
1592 | static int __init tcm_vhost_init(void) | 1610 | static int __init tcm_vhost_init(void) |
1593 | { | 1611 | { |
1594 | int ret = -ENOMEM; | 1612 | int ret = -ENOMEM; |
1595 | 1613 | /* | |
1614 | * Use our own dedicated workqueue for submitting I/O into | ||
1615 | * target core to avoid contention within system_wq. | ||
1616 | */ | ||
1596 | tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); | 1617 | tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); |
1597 | if (!tcm_vhost_workqueue) | 1618 | if (!tcm_vhost_workqueue) |
1598 | goto out; | 1619 | goto out; |
diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h index c983ed21e413..d9e93557d669 100644 --- a/drivers/vhost/tcm_vhost.h +++ b/drivers/vhost/tcm_vhost.h | |||
@@ -47,9 +47,9 @@ struct tcm_vhost_tpg { | |||
47 | /* Vhost port target portal group tag for TCM */ | 47 | /* Vhost port target portal group tag for TCM */ |
48 | u16 tport_tpgt; | 48 | u16 tport_tpgt; |
49 | /* Used to track number of TPG Port/Lun Links wrt to explict I_T Nexus shutdown */ | 49 | /* Used to track number of TPG Port/Lun Links wrt to explict I_T Nexus shutdown */ |
50 | atomic_t tv_tpg_port_count; | 50 | int tv_tpg_port_count; |
51 | /* Used for vhost_scsi device reference to tpg_nexus */ | 51 | /* Used for vhost_scsi device reference to tpg_nexus, protected by tv_tpg_mutex */ |
52 | atomic_t tv_tpg_vhost_count; | 52 | int tv_tpg_vhost_count; |
53 | /* list for tcm_vhost_list */ | 53 | /* list for tcm_vhost_list */ |
54 | struct list_head tv_tpg_list; | 54 | struct list_head tv_tpg_list; |
55 | /* Used to protect access for tpg_nexus */ | 55 | /* Used to protect access for tpg_nexus */ |
@@ -91,11 +91,13 @@ struct tcm_vhost_tport { | |||
91 | 91 | ||
92 | struct vhost_scsi_target { | 92 | struct vhost_scsi_target { |
93 | int abi_version; | 93 | int abi_version; |
94 | unsigned char vhost_wwpn[TRANSPORT_IQN_LEN]; | 94 | char vhost_wwpn[TRANSPORT_IQN_LEN]; |
95 | unsigned short vhost_tpgt; | 95 | unsigned short vhost_tpgt; |
96 | unsigned short reserved; | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | /* VHOST_SCSI specific defines */ | 99 | /* VHOST_SCSI specific defines */ |
99 | #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) | 100 | #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) |
100 | #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) | 101 | #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target) |
101 | #define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, struct vhost_scsi_target) | 102 | /* Changing this breaks userspace. */ |
103 | #define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int) | ||
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 128ce46fa48a..015cea01ae39 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h | |||
@@ -503,8 +503,6 @@ struct se_cmd { | |||
503 | u32 se_ordered_id; | 503 | u32 se_ordered_id; |
504 | /* Total size in bytes associated with command */ | 504 | /* Total size in bytes associated with command */ |
505 | u32 data_length; | 505 | u32 data_length; |
506 | /* SCSI Presented Data Transfer Length */ | ||
507 | u32 cmd_spdtl; | ||
508 | u32 residual_count; | 506 | u32 residual_count; |
509 | u32 orig_fe_lun; | 507 | u32 orig_fe_lun; |
510 | /* Persistent Reservation key */ | 508 | /* Persistent Reservation key */ |