[PATCH 2/2] [Target_Core_Mod/Persistent_Reservations]: Add UNIT ATTENTION support for PROUT SAs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From d3aed0204976bffa99505e606f2909fd61b3b8f3 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Tue, 24 Mar 2009 22:25:36 -0700
Subject: [PATCH 2/2] [Target_Core_Mod/Persistent_Reservations]: Add UNIT ATTENTION support for PROUT SAs

This patch adds support for SAM4 defined UNIT ATTENTION conditions in SPC-3 compliant
Persistent Reservations PROUT Service Actions REGISTER + SARK=0 (UNREGISTER), RELEASE,
and CLEAR.

The respective UNIT ATTENTION ASCQs for the non PROUT SA calling I_T Nexus
ports are ASCQ_2AH_RESERVATIONS_RELEASED, ASCQ_2AH_RESERVATIONS_RELEASED,
and ASCQ_2AH_RESERVATIONS_PREEMPTED.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
 drivers/lio-core/target_core_pr.c |  107 +++++++++++++++++++++++++++++++++---
 1 files changed, 98 insertions(+), 9 deletions(-)

diff --git a/drivers/lio-core/target_core_pr.c b/drivers/lio-core/target_core_pr.c
index d733bae..0ddf54c 100644
--- a/drivers/lio-core/target_core_pr.c
+++ b/drivers/lio-core/target_core_pr.c
@@ -38,6 +38,7 @@
 #include <target_core_hba.h>
 #include <target_core_transport.h>
 #include <target_core_pr.h>
+#include <target_core_ua.h>
 #include <target_core_transport_plugin.h>
 #include <target_core_fabric_ops.h>
 #include <target_core_configfs.h>
@@ -532,12 +533,13 @@ static void core_scsi3_put_pr_reg(t10_pr_registration_t *pr_reg)
 	smp_mb__after_atomic_dec();
 }
 
-static void core_scsi3_check_implict_release(
+static int core_scsi3_check_implict_release(
 	se_device_t *dev,
 	t10_pr_registration_t *pr_reg)
 {
 	se_node_acl_t *nacl = pr_reg->pr_reg_nacl;
 	t10_pr_registration_t *pr_res_holder;
+	int ret = 0;
 
 	spin_lock(&dev->dev_reservation_lock);
 	pr_res_holder = dev->dev_pr_res_holder;
@@ -556,10 +558,12 @@ static void core_scsi3_check_implict_release(
 		 *    field set to zero (see 5.7.11.3).
 		 */
 		__core_scsi3_complete_pro_release(dev, nacl, pr_reg, 0);
-#warning FIXME: Registrants only, UA + RESERVATIONS RELEASED
+		ret = 1;
 #warning FIXME: All Registrants, only release reservation when last registration is freed.
 	}
 	spin_unlock(&dev->dev_reservation_lock);
+
+	return ret;
 }
 
 /*
@@ -681,9 +685,9 @@ static int core_scsi3_emulate_pro_register(
 	se_dev_entry_t *se_deve;
 	se_lun_t *se_lun = SE_LUN(cmd);
 	se_portal_group_t *se_tpg;
-	t10_pr_registration_t *pr_reg;
+	t10_pr_registration_t *pr_reg, *pr_reg_p;
 	t10_reservation_template_t *pr_tmpl = &SU_DEV(dev)->t10_reservation;
-	int ret = 0;
+	int pr_holder = 0, ret = 0, type;
 
 	if (!(se_sess) || !(se_lun)) {
 		printk(KERN_ERR "SPC-3 PR: se_sess || se_lun_t is NULL!\n");
@@ -748,6 +752,8 @@ static int core_scsi3_emulate_pro_register(
 			core_scsi3_put_pr_reg(pr_reg);
 			return PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 		}
+		type = pr_reg->pr_res_type;
+
 		if (!(ignore_key)) {
 			if (res_key != pr_reg->pr_res_key) {
 				printk(KERN_ERR "SPC-3 PR REGISTER: Received"
@@ -771,9 +777,38 @@ static int core_scsi3_emulate_pro_register(
 		 * Nexus.
 		 */
 		if (!(sa_res_key)) {
-			core_scsi3_check_implict_release(SE_DEV(cmd), pr_reg);
+			pr_holder = core_scsi3_check_implict_release(
+					SE_DEV(cmd), pr_reg);
+
 			spin_lock(&pr_tmpl->registration_lock);
+			/*
+			 * Release the calling I_T Nexus registration now..
+			 */
 			__core_scsi3_free_registration(SE_DEV(cmd), pr_reg, 1);
+			/*
+			 * From spc4r17, section 5.7.11.3 Unregistering
+			 *
+			 * If the persistent reservation is a registrants only
+			 * type, the device server shall establish a unit
+			 * attention condition for the initiator port associated
+			 * with every registered I_T nexus except for the I_T
+			 * nexus on which the PERSISTENT RESERVE OUT command was
+			 * received, with the additional sense code set to
+			 * RESERVATIONS RELEASED.
+			 */
+			if (pr_holder &&
+			   ((type == PR_TYPE_WRITE_EXCLUSIVE_REGONLY) ||
+			    (type == PR_TYPE_EXCLUSIVE_ACCESS_REGONLY))) {
+				list_for_each_entry(pr_reg_p,
+						&pr_tmpl->registration_list,
+						pr_reg_list) {
+
+					core_scsi3_ua_allocate(
+						pr_reg_p->pr_reg_nacl,
+						cmd->orig_fe_lun, 0x2A,
+						ASCQ_2AH_RESERVATIONS_RELEASED);
+				}
+			}
 			spin_unlock(&pr_tmpl->registration_lock);
 		} else {
 			/*
@@ -1047,7 +1082,8 @@ static int core_scsi3_emulate_pro_release(
 	se_device_t *dev = cmd->se_dev;
 	se_session_t *se_sess = SE_SESS(cmd);
 	se_lun_t *se_lun = SE_LUN(cmd);
-	t10_pr_registration_t *pr_reg, *pr_res_holder;
+	t10_pr_registration_t *pr_reg, *pr_reg_p, *pr_res_holder;
+	t10_reservation_template_t *pr_tmpl = &SU_DEV(dev)->t10_reservation;
 
 	if (!(se_sess) || !(se_lun)) {
 		printk(KERN_ERR "SPC-3 PR: se_sess || se_lun_t is NULL!\n");
@@ -1137,10 +1173,50 @@ static int core_scsi3_emulate_pro_release(
 		core_scsi3_put_pr_reg(pr_reg);
 		return PYX_TRANSPORT_RESERVATION_CONFLICT;
 	}
+	/*
+	 * In response to a persistent reservation release request from the
+	 * persistent reservation holder the device server shall perform a
+	 * release by doing the following as an uninterrupted series of actions:
+	 * a) Release the persistent reservation;
+	 * b) Not remove any registration(s);
+	 * c) If the released persistent reservation is a registrants only type
+	 * or all registrants type persistent reservation,
+	 *    the device server shall establish a unit attention condition for
+	 *    the initiator port associated with every regis-
+	 *    tered I_T nexus other than I_T nexus on which the PERSISTENT
+	 *    RESERVE OUT command with RELEASE service action was received,
+	 *    with the additional sense code set to RESERVATIONS RELEASED; and
+	 * d) If the persistent reservation is of any other type, the device
+	 *    server shall not establish a unit attention condition.
+	 */
 	__core_scsi3_complete_pro_release(dev, se_sess->se_node_acl,
 			pr_reg, 1);
+
+	if ((type != PR_TYPE_WRITE_EXCLUSIVE_REGONLY) &&
+	    (type != PR_TYPE_EXCLUSIVE_ACCESS_REGONLY) &&
+	    (type != PR_TYPE_WRITE_EXCLUSIVE_ALLREG) &&
+	    (type != PR_TYPE_EXCLUSIVE_ACCESS_ALLREG)) {
+		spin_unlock(&dev->dev_reservation_lock);
+		core_scsi3_put_pr_reg(pr_reg);
+		return 0;
+	}
 	spin_unlock(&dev->dev_reservation_lock);
 
+	spin_lock(&pr_tmpl->registration_lock);
+	list_for_each_entry(pr_reg_p, &pr_tmpl->registration_list,
+			pr_reg_list) {
+		/*
+		 * Do not establish a UNIT ATTENTION condition
+		 * for the calling I_T Nexus
+		 */
+		if (pr_reg_p == pr_reg)
+			continue;
+
+		core_scsi3_ua_allocate(pr_reg_p->pr_reg_nacl, cmd->orig_fe_lun,
+				0x2A, ASCQ_2AH_RESERVATIONS_RELEASED);
+	}
+	spin_unlock(&pr_tmpl->registration_lock);
+
 	core_scsi3_put_pr_reg(pr_reg);
 	return 0;
 }
@@ -1150,9 +1226,11 @@ static int core_scsi3_emulate_pro_clear(
 	u64 res_key)
 {
 	se_device_t *dev = cmd->se_dev;
+	se_node_acl_t *pr_reg_nacl;
 	se_session_t *se_sess = SE_SESS(cmd);
 	t10_reservation_template_t *pr_tmpl = &SU_DEV(dev)->t10_reservation;
 	t10_pr_registration_t *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
+	int calling_it_nexus = 0;
 	/*
 	 * Locate the existing *pr_reg via se_node_acl_t pointers
 	 */
@@ -1199,9 +1277,20 @@ static int core_scsi3_emulate_pro_clear(
 	spin_lock(&pr_tmpl->registration_lock);
 	list_for_each_entry_safe(pr_reg, pr_reg_tmp,
 			&pr_tmpl->registration_list, pr_reg_list) {
-#warning FIXME: UA + RESERVATIONS PREEMPTED for all other registered I_T nexuses
-		__core_scsi3_free_registration(dev, pr_reg,
-					(pr_reg_n == pr_reg) ? 1 : 0);
+
+		calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
+		pr_reg_nacl = pr_reg->pr_reg_nacl;
+		__core_scsi3_free_registration(dev, pr_reg, calling_it_nexus);
+		/*
+		 * e) Establish a unit attention condition for the initiator
+		 *    port associated with every registered I_T nexus other
+		 *    than the I_T nexus on which the PERSISTENT RESERVE OUT
+		 *    command with CLEAR service action was received, with the
+		 *    additional sense code set to RESERVATIONS PREEMPTED.
+		 */
+		if (!(calling_it_nexus))
+			core_scsi3_ua_allocate(pr_reg_nacl, cmd->orig_fe_lun,
+				0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED);
 	}
 	spin_unlock(&pr_tmpl->registration_lock);
 
-- 
1.5.4.1



--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux