aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2012-07-30 16:30:00 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2012-08-16 20:33:40 -0400
commit101998f6fcd680ed12d85633b81504feb1cb0667 (patch)
treee2d323c4e7a2f09cadd675d59e003330130c6563 /drivers/vhost
parentf0e0e9bba5eed2086f6001be14f21566a49bed10 (diff)
tcm_vhost: Post-merge review changes requested by MST
This patch contains the post RFC-v5 (post-merge) changes, this includes: - Add locking comment - Move vhost_scsi_complete_cmd ahead of TFO callbacks in order to drop forward declarations - Drop extra '!= NULL' usage in vhost_scsi_complete_cmd_work() - Change vhost_scsi_*_handle_kick() to use pr_debug - Fix possible race in vhost_scsi_set_endpoint() for vs->vs_tpg checking + assignment. - Convert tv_tpg->tpg_vhost_count + ->tv_tpg_port_count from atomic_t -> int, and make sure reference is protected by ->tv_tpg_mutex. - Drop unnecessary vhost_scsi->vhost_ref_cnt - Add 'err:' label for exception path in vhost_scsi_clear_endpoint() - Add enum for VQ numbers, add usage in vhost_scsi_open() - Add vhost_scsi_flush() + vhost_scsi_flush_vq() following drivers/vhost/net.c - Add smp_wmb() + vhost_scsi_flush() call during vhost_scsi_set_features() - Drop unnecessary copy_from_user() usage with GET_ABI_VERSION ioctl - Add missing vhost_scsi_compat_ioctl() caller for vhost_scsi_fops - Fix function parameter definition first line to follow existing vhost code style - Change 'vHost' usage -> 'vhost' in handful of locations - Change -EPERM -> -EBUSY usage for two failures in tcm_vhost_drop_nexus() - Add comment for tcm_vhost_workqueue in tcm_vhost_init() - Make GET_ABI_VERSION return 'int' + add comment in tcm_vhost.h Reported-by: Michael S. Tsirkin <mst@redhat.com> Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Cc: Anthony Liguori <aliguori@us.ibm.com> Cc: Zhi Yong Wu <wuzhy@cn.ibm.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/vhost')
-rw-r--r--drivers/vhost/tcm_vhost.c195
-rw-r--r--drivers/vhost/tcm_vhost.h9
2 files changed, 111 insertions, 93 deletions
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c
index 481af88a5ff5..74b2edaaf1f6 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,
@@ -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,7 +989,7 @@ 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:
@@ -988,12 +1003,7 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
988 1003
989 return vhost_scsi_clear_endpoint(vs, &backend); 1004 return vhost_scsi_clear_endpoint(vs, &backend);
990 case VHOST_SCSI_GET_ABI_VERSION: 1005 case VHOST_SCSI_GET_ABI_VERSION:
991 if (copy_from_user(&backend, argp, sizeof backend)) 1006 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; 1007 return -EFAULT;
998 return 0; 1008 return 0;
999 case VHOST_GET_FEATURES: 1009 case VHOST_GET_FEATURES:
@@ -1013,11 +1023,21 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
1013 } 1023 }
1014} 1024}
1015 1025
1026#ifdef CONFIG_COMPAT
1027static long vhost_scsi_compat_ioctl(struct file *f, unsigned int ioctl,
1028 unsigned long arg)
1029{
1030 return vhost_scsi_ioctl(f, ioctl, (unsigned long)compat_ptr(arg));
1031}
1032#endif
1033
1016static const struct file_operations vhost_scsi_fops = { 1034static const struct file_operations vhost_scsi_fops = {
1017 .owner = THIS_MODULE, 1035 .owner = THIS_MODULE,
1018 .release = vhost_scsi_release, 1036 .release = vhost_scsi_release,
1019 .unlocked_ioctl = vhost_scsi_ioctl, 1037 .unlocked_ioctl = vhost_scsi_ioctl,
1020 /* TODO compat ioctl? */ 1038#ifdef CONFIG_COMPAT
1039 .compat_ioctl = vhost_scsi_compat_ioctl,
1040#endif
1021 .open = vhost_scsi_open, 1041 .open = vhost_scsi_open,
1022 .llseek = noop_llseek, 1042 .llseek = noop_llseek,
1023}; 1043};
@@ -1054,28 +1074,28 @@ static char *tcm_vhost_dump_proto_id(struct tcm_vhost_tport *tport)
1054 return "Unknown"; 1074 return "Unknown";
1055} 1075}
1056 1076
1057static int tcm_vhost_port_link( 1077static int tcm_vhost_port_link(struct se_portal_group *se_tpg,
1058 struct se_portal_group *se_tpg,
1059 struct se_lun *lun) 1078 struct se_lun *lun)
1060{ 1079{
1061 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, 1080 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
1062 struct tcm_vhost_tpg, se_tpg); 1081 struct tcm_vhost_tpg, se_tpg);
1063 1082
1064 atomic_inc(&tv_tpg->tv_tpg_port_count); 1083 mutex_lock(&tv_tpg->tv_tpg_mutex);
1065 smp_mb__after_atomic_inc(); 1084 tv_tpg->tv_tpg_port_count++;
1085 mutex_unlock(&tv_tpg->tv_tpg_mutex);
1066 1086
1067 return 0; 1087 return 0;
1068} 1088}
1069 1089
1070static void tcm_vhost_port_unlink( 1090static void tcm_vhost_port_unlink(struct se_portal_group *se_tpg,
1071 struct se_portal_group *se_tpg,
1072 struct se_lun *se_lun) 1091 struct se_lun *se_lun)
1073{ 1092{
1074 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, 1093 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
1075 struct tcm_vhost_tpg, se_tpg); 1094 struct tcm_vhost_tpg, se_tpg);
1076 1095
1077 atomic_dec(&tv_tpg->tv_tpg_port_count); 1096 mutex_lock(&tv_tpg->tv_tpg_mutex);
1078 smp_mb__after_atomic_dec(); 1097 tv_tpg->tv_tpg_port_count--;
1098 mutex_unlock(&tv_tpg->tv_tpg_mutex);
1079} 1099}
1080 1100
1081static struct se_node_acl *tcm_vhost_make_nodeacl( 1101static struct se_node_acl *tcm_vhost_make_nodeacl(
@@ -1122,8 +1142,7 @@ static void tcm_vhost_drop_nodeacl(struct se_node_acl *se_acl)
1122 kfree(nacl); 1142 kfree(nacl);
1123} 1143}
1124 1144
1125static int tcm_vhost_make_nexus( 1145static int tcm_vhost_make_nexus(struct tcm_vhost_tpg *tv_tpg,
1126 struct tcm_vhost_tpg *tv_tpg,
1127 const char *name) 1146 const char *name)
1128{ 1147{
1129 struct se_portal_group *se_tpg; 1148 struct se_portal_group *se_tpg;
@@ -1168,7 +1187,7 @@ static int tcm_vhost_make_nexus(
1168 return -ENOMEM; 1187 return -ENOMEM;
1169 } 1188 }
1170 /* 1189 /*
1171 * Now register the TCM vHost virtual I_T Nexus as active with the 1190 * Now register the TCM vhost virtual I_T Nexus as active with the
1172 * call to __transport_register_session() 1191 * call to __transport_register_session()
1173 */ 1192 */
1174 __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl, 1193 __transport_register_session(se_tpg, tv_nexus->tvn_se_sess->se_node_acl,
@@ -1179,8 +1198,7 @@ static int tcm_vhost_make_nexus(
1179 return 0; 1198 return 0;
1180} 1199}
1181 1200
1182static int tcm_vhost_drop_nexus( 1201static int tcm_vhost_drop_nexus(struct tcm_vhost_tpg *tpg)
1183 struct tcm_vhost_tpg *tpg)
1184{ 1202{
1185 struct se_session *se_sess; 1203 struct se_session *se_sess;
1186 struct tcm_vhost_nexus *tv_nexus; 1204 struct tcm_vhost_nexus *tv_nexus;
@@ -1198,27 +1216,27 @@ static int tcm_vhost_drop_nexus(
1198 return -ENODEV; 1216 return -ENODEV;
1199 } 1217 }
1200 1218
1201 if (atomic_read(&tpg->tv_tpg_port_count)) { 1219 if (tpg->tv_tpg_port_count != 0) {
1202 mutex_unlock(&tpg->tv_tpg_mutex); 1220 mutex_unlock(&tpg->tv_tpg_mutex);
1203 pr_err("Unable to remove TCM_vHost I_T Nexus with" 1221 pr_err("Unable to remove TCM_vhost I_T Nexus with"
1204 " active TPG port count: %d\n", 1222 " active TPG port count: %d\n",
1205 atomic_read(&tpg->tv_tpg_port_count)); 1223 tpg->tv_tpg_port_count);
1206 return -EPERM; 1224 return -EBUSY;
1207 } 1225 }
1208 1226
1209 if (atomic_read(&tpg->tv_tpg_vhost_count)) { 1227 if (tpg->tv_tpg_vhost_count != 0) {
1210 mutex_unlock(&tpg->tv_tpg_mutex); 1228 mutex_unlock(&tpg->tv_tpg_mutex);
1211 pr_err("Unable to remove TCM_vHost I_T Nexus with" 1229 pr_err("Unable to remove TCM_vhost I_T Nexus with"
1212 " active TPG vhost count: %d\n", 1230 " active TPG vhost count: %d\n",
1213 atomic_read(&tpg->tv_tpg_vhost_count)); 1231 tpg->tv_tpg_vhost_count);
1214 return -EPERM; 1232 return -EBUSY;
1215 } 1233 }
1216 1234
1217 pr_debug("TCM_vHost_ConfigFS: Removing I_T Nexus to emulated" 1235 pr_debug("TCM_vhost_ConfigFS: Removing I_T Nexus to emulated"
1218 " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport), 1236 " %s Initiator Port: %s\n", tcm_vhost_dump_proto_id(tpg->tport),
1219 tv_nexus->tvn_se_sess->se_node_acl->initiatorname); 1237 tv_nexus->tvn_se_sess->se_node_acl->initiatorname);
1220 /* 1238 /*
1221 * Release the SCSI I_T Nexus to the emulated vHost Target Port 1239 * Release the SCSI I_T Nexus to the emulated vhost Target Port
1222 */ 1240 */
1223 transport_deregister_session(tv_nexus->tvn_se_sess); 1241 transport_deregister_session(tv_nexus->tvn_se_sess);
1224 tpg->tpg_nexus = NULL; 1242 tpg->tpg_nexus = NULL;
@@ -1228,8 +1246,7 @@ static int tcm_vhost_drop_nexus(
1228 return 0; 1246 return 0;
1229} 1247}
1230 1248
1231static ssize_t tcm_vhost_tpg_show_nexus( 1249static ssize_t tcm_vhost_tpg_show_nexus(struct se_portal_group *se_tpg,
1232 struct se_portal_group *se_tpg,
1233 char *page) 1250 char *page)
1234{ 1251{
1235 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg, 1252 struct tcm_vhost_tpg *tv_tpg = container_of(se_tpg,
@@ -1250,8 +1267,7 @@ static ssize_t tcm_vhost_tpg_show_nexus(
1250 return ret; 1267 return ret;
1251} 1268}
1252 1269
1253static ssize_t tcm_vhost_tpg_store_nexus( 1270static ssize_t tcm_vhost_tpg_store_nexus(struct se_portal_group *se_tpg,
1254 struct se_portal_group *se_tpg,
1255 const char *page, 1271 const char *page,
1256 size_t count) 1272 size_t count)
1257{ 1273{
@@ -1336,8 +1352,7 @@ static struct configfs_attribute *tcm_vhost_tpg_attrs[] = {
1336 NULL, 1352 NULL,
1337}; 1353};
1338 1354
1339static struct se_portal_group *tcm_vhost_make_tpg( 1355static struct se_portal_group *tcm_vhost_make_tpg(struct se_wwn *wwn,
1340 struct se_wwn *wwn,
1341 struct config_group *group, 1356 struct config_group *group,
1342 const char *name) 1357 const char *name)
1343{ 1358{
@@ -1385,7 +1400,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg)
1385 list_del(&tpg->tv_tpg_list); 1400 list_del(&tpg->tv_tpg_list);
1386 mutex_unlock(&tcm_vhost_mutex); 1401 mutex_unlock(&tcm_vhost_mutex);
1387 /* 1402 /*
1388 * Release the virtual I_T Nexus for this vHost TPG 1403 * Release the virtual I_T Nexus for this vhost TPG
1389 */ 1404 */
1390 tcm_vhost_drop_nexus(tpg); 1405 tcm_vhost_drop_nexus(tpg);
1391 /* 1406 /*
@@ -1395,8 +1410,7 @@ static void tcm_vhost_drop_tpg(struct se_portal_group *se_tpg)
1395 kfree(tpg); 1410 kfree(tpg);
1396} 1411}
1397 1412
1398static struct se_wwn *tcm_vhost_make_tport( 1413static struct se_wwn *tcm_vhost_make_tport(struct target_fabric_configfs *tf,
1399 struct target_fabric_configfs *tf,
1400 struct config_group *group, 1414 struct config_group *group,
1401 const char *name) 1415 const char *name)
1402{ 1416{
@@ -1592,7 +1606,10 @@ static void tcm_vhost_deregister_configfs(void)
1592static int __init tcm_vhost_init(void) 1606static int __init tcm_vhost_init(void)
1593{ 1607{
1594 int ret = -ENOMEM; 1608 int ret = -ENOMEM;
1595 1609 /*
1610 * Use our own dedicated workqueue for submitting I/O into
1611 * target core to avoid contention within system_wq.
1612 */
1596 tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0); 1613 tcm_vhost_workqueue = alloc_workqueue("tcm_vhost", 0, 0);
1597 if (!tcm_vhost_workqueue) 1614 if (!tcm_vhost_workqueue)
1598 goto out; 1615 goto out;
diff --git a/drivers/vhost/tcm_vhost.h b/drivers/vhost/tcm_vhost.h
index c983ed21e413..eff42df14de9 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 */
@@ -98,4 +98,5 @@ struct vhost_scsi_target {
98/* VHOST_SCSI specific defines */ 98/* VHOST_SCSI specific defines */
99#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target) 99#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) 100#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) 101/* Changing this breaks userspace. */
102#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)