aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-22 13:42:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-22 13:42:30 -0400
commit092369943623749b6c2321d65aaf4ec432cd3d04 (patch)
tree181250d4f9fe59f5805f31fae2cba1a6f918228c
parent2e2d8c93aec7c0f995bf140a00fb15ca2e07ddd4 (diff)
parentaf74115eed22698f771fec1287a864975c9a6671 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target fixes from Nicholas Bellinger: "The executive summary includes: - Post-merge review comments for tcm_vhost (MST + nab) - Avoid debugging overhead when not debugging for tcm-fc(FCoE) (MDR) - Fix NULL pointer dereference bug on alloc_page failulre (Yi Zou) - Fix REPORT_LUNs regression bug with pSCSI export (AlexE + nab) - Fix regression bug with handling of zero-length data CDBs (nab) - Fix vhost_scsi_target structure alignment (MST) Thanks again to everyone who contributed a bugfix patch, gave review feedback on tcm_vhost code, and/or reported a bug during their own testing over the last weeks. There is one other outstanding bug reported by Roland recently related to SCSI transfer length overflow handling, for which the current proposed bugfix has been left in queue pending further testing with other non iscsi-target based fabric drivers. As the patch is verified with loopback (local SGL memory from SCSI LLD) + tcm_qla2xxx (TCM allocated SGL memory mapped to PCI HW) fabric ports, it will be included into the next 3.6-rc-fixes PULL request." * git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: target: Remove unused se_cmd.cmd_spdtl tcm_fc: rcu_deref outside rcu lock/unlock section tcm_vhost: Fix vhost_scsi_target structure alignment target: Fix regression bug with handling of zero-length data CDBs target/pscsi: Fix bug with REPORT_LUNs handling for SCSI passthrough tcm_vhost: Change vhost_scsi_target->vhost_wwpn to char * target: fix NULL pointer dereference bug alloc_page() fails to get memory tcm_fc: Avoid debug overhead when not debugging tcm_vhost: Post-merge review changes requested by MST tcm_vhost: Fix incorrect IS_ERR() usage in vhost_scsi_map_iov_to_sgl
-rw-r--r--drivers/target/target_core_pscsi.c9
-rw-r--r--drivers/target/target_core_transport.c15
-rw-r--r--drivers/target/tcm_fc/tcm_fc.h1
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c8
-rw-r--r--drivers/target/tcm_fc/tfc_sess.c4
-rw-r--r--drivers/vhost/tcm_vhost.c203
-rw-r--r--drivers/vhost/tcm_vhost.h12
-rw-r--r--include/target/target_core_base.h2
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
2296out: 2294out:
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;
131extern struct mutex ft_lport_lock; 131extern struct mutex ft_lport_lock;
132extern struct fc4_prov ft_prov; 132extern struct fc4_prov ft_prov;
133extern struct target_fabric_configfs *ft_configfs; 133extern struct target_fabric_configfs *ft_configfs;
134extern 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 */
51void ft_dump_cmd(struct ft_cmd *cmd, const char *caller) 51static 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
83void 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
83static void ft_free_cmd(struct ft_cmd *cmd) 89static 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
56enum {
57 VHOST_SCSI_VQ_CTL = 0,
58 VHOST_SCSI_VQ_EVT = 1,
59 VHOST_SCSI_VQ_IO = 2,
60};
61
56struct vhost_scsi { 62struct 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
134static u32 tcm_vhost_get_pr_transport_id( 139static 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
165static u32 tcm_vhost_get_pr_transport_id_len( 169static 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
195static char *tcm_vhost_parse_pr_out_transport_id( 198static 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
239static void tcm_vhost_release_fabric_acl( 241static 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
300static void vhost_scsi_complete_cmd(struct tcm_vhost_cmd *); 301static 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
302static int tcm_vhost_queue_data_in(struct se_cmd *se_cmd) 312static 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
411static 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
424static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd( 421static 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
788static void vhost_scsi_ctl_handle_kick(struct vhost_work *work) 785static 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
793static void vhost_scsi_evt_handle_kick(struct vhost_work *work) 790static 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
798static void vhost_scsi_handle_kick(struct vhost_work *work) 795static 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
905err:
906 mutex_unlock(&vs->dev.mutex);
907 return ret;
906} 908}
907 909
908static int vhost_scsi_open(struct inode *inode, struct file *f) 910static 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
954static void vhost_scsi_flush_vq(struct vhost_scsi *vs, int index)
955{
956 vhost_poll_flush(&vs->dev.vqs[index].poll);
957}
958
959static 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
952static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) 966static 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
1031static 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
1016static const struct file_operations vhost_scsi_fops = { 1038static 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
1057static int tcm_vhost_port_link( 1081static 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
1070static void tcm_vhost_port_unlink( 1094static 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
1081static struct se_node_acl *tcm_vhost_make_nodeacl( 1105static 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
1125static int tcm_vhost_make_nexus( 1149static 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
1182static int tcm_vhost_drop_nexus( 1205static 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
1231static ssize_t tcm_vhost_tpg_show_nexus( 1253static 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
1253static ssize_t tcm_vhost_tpg_store_nexus( 1274static 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
1339static struct se_portal_group *tcm_vhost_make_tpg( 1359static 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
1398static struct se_wwn *tcm_vhost_make_tport( 1417static 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)
1592static int __init tcm_vhost_init(void) 1610static 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
92struct vhost_scsi_target { 92struct 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 */