aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */