aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-02-19 19:53:07 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-02-20 16:01:17 -0500
commit7474f52a82d51da2e6110e91bba8b000cb9cf803 (patch)
tree7ea5e1f43284aa10debb071398abd4c10178a956
parent394d62ba4580a74afc90bf0e007e10291bf447cc (diff)
tcm_qla2xxx: Perform configfs depend/undepend for base_tpg
This patch performs configfs_depend_item() during TPG enable for base_tpg (eg: non-NPIV) ports, and configfs_undepend_item() during TPG disable for base_tpg. This is done to ensure that any attempt to configfs rmdir a base_tpg with active NPIV ports will fail with -EBUSY, until all associated NPIV ports have been explicitly shutdown and base_tpg disabled. Note that the actual configfs_[un]depend_item() is done from seperate process context, as these are not intended to be called directly from configfs callbacks. Cc: Sawan Chandak <sawan.chandak@qlogic.com> Cc: Quinn Tran <quinn.tran@qlogic.com> Cc: Saurav Kashyap <saurav.kashyap@qlogic.com> Cc: Giridhar Malavali <giridhar.malavali@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c72
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.h3
2 files changed, 61 insertions, 14 deletions
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index db43b2893525..5bdc44035981 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -941,15 +941,41 @@ static ssize_t tcm_qla2xxx_tpg_show_enable(
941 atomic_read(&tpg->lport_tpg_enabled)); 941 atomic_read(&tpg->lport_tpg_enabled));
942} 942}
943 943
944static void tcm_qla2xxx_depend_tpg(struct work_struct *work)
945{
946 struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
947 struct tcm_qla2xxx_tpg, tpg_base_work);
948 struct se_portal_group *se_tpg = &base_tpg->se_tpg;
949 struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
950
951 if (!configfs_depend_item(se_tpg->se_tpg_tfo->tf_subsys,
952 &se_tpg->tpg_group.cg_item)) {
953 atomic_set(&base_tpg->lport_tpg_enabled, 1);
954 qlt_enable_vha(base_vha);
955 }
956 complete(&base_tpg->tpg_base_comp);
957}
958
959static void tcm_qla2xxx_undepend_tpg(struct work_struct *work)
960{
961 struct tcm_qla2xxx_tpg *base_tpg = container_of(work,
962 struct tcm_qla2xxx_tpg, tpg_base_work);
963 struct se_portal_group *se_tpg = &base_tpg->se_tpg;
964 struct scsi_qla_host *base_vha = base_tpg->lport->qla_vha;
965
966 if (!qlt_stop_phase1(base_vha->vha_tgt.qla_tgt)) {
967 atomic_set(&base_tpg->lport_tpg_enabled, 0);
968 configfs_undepend_item(se_tpg->se_tpg_tfo->tf_subsys,
969 &se_tpg->tpg_group.cg_item);
970 }
971 complete(&base_tpg->tpg_base_comp);
972}
973
944static ssize_t tcm_qla2xxx_tpg_store_enable( 974static ssize_t tcm_qla2xxx_tpg_store_enable(
945 struct se_portal_group *se_tpg, 975 struct se_portal_group *se_tpg,
946 const char *page, 976 const char *page,
947 size_t count) 977 size_t count)
948{ 978{
949 struct se_wwn *se_wwn = se_tpg->se_tpg_wwn;
950 struct tcm_qla2xxx_lport *lport = container_of(se_wwn,
951 struct tcm_qla2xxx_lport, lport_wwn);
952 struct scsi_qla_host *vha = lport->qla_vha;
953 struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg, 979 struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
954 struct tcm_qla2xxx_tpg, se_tpg); 980 struct tcm_qla2xxx_tpg, se_tpg);
955 unsigned long op; 981 unsigned long op;
@@ -964,19 +990,28 @@ static ssize_t tcm_qla2xxx_tpg_store_enable(
964 pr_err("Illegal value for tpg_enable: %lu\n", op); 990 pr_err("Illegal value for tpg_enable: %lu\n", op);
965 return -EINVAL; 991 return -EINVAL;
966 } 992 }
967
968 if (op) { 993 if (op) {
969 atomic_set(&tpg->lport_tpg_enabled, 1); 994 if (atomic_read(&tpg->lport_tpg_enabled))
970 qlt_enable_vha(vha); 995 return -EEXIST;
996
997 INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_depend_tpg);
971 } else { 998 } else {
972 if (!vha->vha_tgt.qla_tgt) { 999 if (!atomic_read(&tpg->lport_tpg_enabled))
973 pr_err("struct qla_hw_data *vha->vha_tgt.qla_tgt is NULL\n"); 1000 return count;
974 return -ENODEV; 1001
975 } 1002 INIT_WORK(&tpg->tpg_base_work, tcm_qla2xxx_undepend_tpg);
976 atomic_set(&tpg->lport_tpg_enabled, 0);
977 qlt_stop_phase1(vha->vha_tgt.qla_tgt);
978 } 1003 }
1004 init_completion(&tpg->tpg_base_comp);
1005 schedule_work(&tpg->tpg_base_work);
1006 wait_for_completion(&tpg->tpg_base_comp);
979 1007
1008 if (op) {
1009 if (!atomic_read(&tpg->lport_tpg_enabled))
1010 return -ENODEV;
1011 } else {
1012 if (atomic_read(&tpg->lport_tpg_enabled))
1013 return -EPERM;
1014 }
980 return count; 1015 return count;
981} 1016}
982 1017
@@ -1703,6 +1738,9 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
1703 struct scsi_qla_host *npiv_vha; 1738 struct scsi_qla_host *npiv_vha;
1704 struct tcm_qla2xxx_lport *lport = 1739 struct tcm_qla2xxx_lport *lport =
1705 (struct tcm_qla2xxx_lport *)target_lport_ptr; 1740 (struct tcm_qla2xxx_lport *)target_lport_ptr;
1741 struct tcm_qla2xxx_lport *base_lport =
1742 (struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
1743 struct tcm_qla2xxx_tpg *base_tpg;
1706 struct fc_vport_identifiers vport_id; 1744 struct fc_vport_identifiers vport_id;
1707 1745
1708 if (!qla_tgt_mode_enabled(base_vha)) { 1746 if (!qla_tgt_mode_enabled(base_vha)) {
@@ -1710,6 +1748,13 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
1710 return -EPERM; 1748 return -EPERM;
1711 } 1749 }
1712 1750
1751 if (!base_lport || !base_lport->tpg_1 ||
1752 !atomic_read(&base_lport->tpg_1->lport_tpg_enabled)) {
1753 pr_err("qla2xxx base_lport or tpg_1 not available\n");
1754 return -EPERM;
1755 }
1756 base_tpg = base_lport->tpg_1;
1757
1713 memset(&vport_id, 0, sizeof(vport_id)); 1758 memset(&vport_id, 0, sizeof(vport_id));
1714 vport_id.port_name = npiv_wwpn; 1759 vport_id.port_name = npiv_wwpn;
1715 vport_id.node_name = npiv_wwnn; 1760 vport_id.node_name = npiv_wwnn;
@@ -1728,7 +1773,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
1728 npiv_vha = (struct scsi_qla_host *)vport->dd_data; 1773 npiv_vha = (struct scsi_qla_host *)vport->dd_data;
1729 npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr; 1774 npiv_vha->vha_tgt.target_lport_ptr = target_lport_ptr;
1730 lport->qla_vha = npiv_vha; 1775 lport->qla_vha = npiv_vha;
1731
1732 scsi_host_get(npiv_vha->host); 1776 scsi_host_get(npiv_vha->host);
1733 return 0; 1777 return 0;
1734} 1778}
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
index 275d8b9a7a34..a90966d3c0d6 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h
@@ -43,6 +43,9 @@ struct tcm_qla2xxx_tpg {
43 struct tcm_qla2xxx_tpg_attrib tpg_attrib; 43 struct tcm_qla2xxx_tpg_attrib tpg_attrib;
44 /* Returned by tcm_qla2xxx_make_tpg() */ 44 /* Returned by tcm_qla2xxx_make_tpg() */
45 struct se_portal_group se_tpg; 45 struct se_portal_group se_tpg;
46 /* Items for dealing with configfs_depend_item */
47 struct completion tpg_base_comp;
48 struct work_struct tpg_base_work;
46}; 49};
47 50
48struct tcm_qla2xxx_fc_loopid { 51struct tcm_qla2xxx_fc_loopid {