[PATCH 1/2] [Target_Core_Mod/PERSISTENT_RESERVATION]: Add ServiceAction RESERVE/RELEASE w/ all_tg_pt=[0,1]

From: Nicholas A. Bellinger
Date: Wed Jan 28 2009 - 02:43:20 EST


>From d47e48470fce00264620252797aa7665bf51ecf4 Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Tue, 27 Jan 2009 23:02:54 -0800
Subject: [PATCH 1/2] [Target_Core_Mod/PERSISTENT_RESERVATION]: Add Service Action RESERVE/RELEASE w/ all_tg_pt=[0,1]

This patch adds running logic for PROUT Service Actions RESERVE and RELEASE for
PR_TYPE_WRITE_EXCLUSIVE and PR_TYPE_EXCLUSIVE_ACCESS PR Types using All Target Ports Bit
(all_tg_pt) Enabled and Disabled. Here is output from the kernel ringbuffer during
a successful PROUT REGISTER -> PROUT RESERVE -> PRIN READ_RESERVATION -> PROUT RELEASE
PROUT UNREGISTER using sg_persist:

SPC-3 PR [iSCSI] Service Action: REGISTER Initiator Node: iqn.1993-08.org.debian:01:2dadf92d0ef
SPC-3 PR [iSCSI] for ALL TCM Subsystem iblock Object Target Port(s)
SPC-3 PR [iSCSI] SA Res Key: 0x000000005678efff PRgeneration: 0x00000000
SPC-3 PR [iSCSI] Service Action: RESERVE created new reservation holder TYPE: Write Exclusive Access ALL_TG_PT: 1
SPC-3 PR [iSCSI] RESERVE Node: iqn.1993-08.org.debian:01:2dadf92d0ef
SPC-3 PR [iSCSI] Service Action: RELEASE cleared reservation holder TYPE: Write Exclusive Access ALL_TG_PT: 1
SPC-3 PR [iSCSI] RELEASE Node: iqn.1993-08.org.debian:01:2dadf92d0ef
SPC-3 PR [iSCSI] Service Action: UNREGISTER Initiator Node: iqn.1993-08.org.debian:01:2dadf92d0ef
SPC-3 PR [iSCSI] for ALL TCM Subsystem iblock Object Target Port(s)
SPC-3 PR [iSCSI] SA Res Key: 0x000000005678efff PRgeneration: 0x00000000

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/lio-core/target_core_base.h | 3 +-
drivers/lio-core/target_core_pr.c | 354 +++++++++++++++++++++++++++++++++-
drivers/lio-core/target_core_pr.h | 1 +
3 files changed, 346 insertions(+), 12 deletions(-)

diff --git a/drivers/lio-core/target_core_base.h b/drivers/lio-core/target_core_base.h
index 3523023..e10538e 100644
--- a/drivers/lio-core/target_core_base.h
+++ b/drivers/lio-core/target_core_base.h
@@ -231,6 +231,7 @@ typedef struct t10_pr_registration_s {
u64 pr_res_key;
struct se_node_acl_s *pr_reg_nacl;
struct se_dev_entry_s *pr_reg_deve;
+ struct se_lun_s *pr_reg_lun_single_tg_pt; /* Used when pr_reg_all_tg_pt=0 */
struct list_head pr_reg_list;
} t10_pr_registration_t;

@@ -570,6 +571,7 @@ typedef struct se_device_s {
spinlock_t se_port_lock;
struct se_node_acl_s *dev_reserved_node_acl; /* Used for legacy SPC-2 reservationsa */
struct t10_pr_registration_s *dev_pr_res_holder; /* Used for SPC-3 Persistent Reservations */
+ struct se_lun_s *dev_pr_tg_port_res_lun; /* Used for PR all_tgt_pt=0 */
struct list_head dev_sep_list;
struct timer_list dev_status_timer;
struct task_struct *process_thread; /* Pointer to descriptor for processing thread */
@@ -640,7 +642,6 @@ typedef struct se_lun_s {
se_lun_acl_t *lun_acl_head;
se_lun_acl_t *lun_acl_tail;
se_device_t *se_dev;
- struct t10_pr_registration_s *lun_pr_res_holder; /* Used for SPC-3 Persistent Reservations */
void *lun_type_ptr;
struct config_group lun_group;
struct se_obj_lun_type_s *lun_obj_api;
diff --git a/drivers/lio-core/target_core_pr.c b/drivers/lio-core/target_core_pr.c
index 41fdf89..051d678 100644
--- a/drivers/lio-core/target_core_pr.c
+++ b/drivers/lio-core/target_core_pr.c
@@ -332,6 +332,13 @@ static t10_pr_registration_t *core_scsi3_alloc_registration (
pr_reg->pr_res_key = sa_res_key;
pr_reg->pr_reg_all_tg_pt = all_tg_pt;
/*
+ * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3
+ * Basic PERSISTENT RESERVER OUT parameter list, page 290
+ */
+ if (!(pr_reg->pr_reg_all_tg_pt))
+ pr_reg->pr_reg_lun_single_tg_pt = deve->se_lun;
+
+ /*
* Increment PRgeneration counter for se_device_t upon a successful
* REGISTER, see spc4r17 section 6.3.2 READ_KEYS service action
*/
@@ -344,7 +351,7 @@ static t10_pr_registration_t *core_scsi3_alloc_registration (
deve->deve_flags |= DEF_PR_REGISTERED;
printk("SPC-3 PR [%s] Service Action: REGISTER Initiator Node: %s\n",
tfo->get_fabric_name(), nacl->initiatorname);
- printk("SPC-3 PR [%s] for %s TCM Subsystem %s Object Port(s)\n",
+ printk("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target Port(s)\n",
tfo->get_fabric_name(), (pr_reg->pr_reg_all_tg_pt) ?
"ALL" : "SINGLE", TRANSPORT(dev)->name);
printk("SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration: 0x%08x\n",
@@ -386,7 +393,7 @@ static void core_scsi3_free_registration (

printk("SPC-3 PR [%s] Service Action: UNREGISTER Initiator Node: %s\n",
tfo->get_fabric_name(), nacl->initiatorname);
- printk("SPC-3 PR [%s] for %s TCM Subsystem %s Object Port(s)\n",
+ printk("SPC-3 PR [%s] for %s TCM Subsystem %s Object Target Port(s)\n",
tfo->get_fabric_name(), (pr_reg->pr_reg_all_tg_pt) ?
"ALL" : "SINGLE", TRANSPORT(dev)->name);
printk("SPC-3 PR [%s] SA Res Key: 0x%016Lx PRgeneration: 0x%08x\n",
@@ -432,7 +439,6 @@ static int core_scsi3_emulate_pro_register (
int all_tg_pt,
int spec_i_pt)
{
- se_subsystem_dev_t *su_dev = SU_DEV(cmd->se_dev);
se_session_t *se_sess = SE_SESS(cmd);
se_dev_entry_t *se_deve;
se_lun_t *se_lun = SE_LUN(cmd);
@@ -499,7 +505,7 @@ static int core_scsi3_emulate_pro_register (
return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
}
if (res_key != pr_reg->pr_res_key) {
- printk(KERN_ERR "SPC-3 PR: Received res_key: 0x%016Lx"
+ printk(KERN_ERR "SPC-3 PR REGISTER: Received res_key: 0x%016Lx"
" does not match existing SA REGISTER res_key:"
" 0x%016Lx\n", res_key, pr_reg->pr_res_key);
return(PYX_TRANSPORT_RESERVATION_CONFLICT);
@@ -534,21 +540,349 @@ static int core_scsi3_emulate_pro_register (
return(0);
}

-static int core_scsi3_emulate_pro_reserve (
+extern unsigned char *core_scsi3_pr_dump_type (int type)
+{
+ switch (type) {
+ case PR_TYPE_WRITE_EXCLUSIVE:
+ return("Write Exclusive Access");
+ case PR_TYPE_EXCLUSIVE_ACCESS:
+ return("Exclusive Access");
+ case PR_TYPE_WRITE_EXCLUSIVE_REGONLY:
+ return("Write Exclusive Access, Registrants Only");
+ case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
+ return("Exclusive Access, Registrants Only");
+ case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
+ return("Write Exclusive Access, All Registrants");
+ case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
+ return("Exclusive Access, All Registrants");
+ default:
+ break;
+ }
+
+ return("Unknown SPC-3 PR Type");
+}
+
+static int core_scsi3_pro_reserve (
se_cmd_t *cmd,
+ se_device_t *dev,
int type,
int scope,
u64 res_key)
{
+ se_session_t *se_sess = SE_SESS(cmd);
+ 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, *pr_res_holder;
+
+ if (!(se_sess) || !(se_lun)) {
+ printk(KERN_ERR "SPC-3 PR: se_sess || se_lun_t is NULL!\n");
+ return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+ }
+ se_tpg = se_sess->se_tpg;
+ se_deve = &se_sess->se_node_acl->device_list[se_lun->unpacked_lun];
+ /*
+ * Locate the existing *pr_reg via se_node_acl_t pointers
+ */
+ pr_reg = core_scsi3_locate_pr_reg(SE_DEV(cmd), se_sess->se_node_acl);
+ if (!(pr_reg)) {
+ printk(KERN_ERR "SPC-3 PR: Unable to locate"
+ " PR_REGISTERED *pr_reg\n");
+ return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+ }
+ /*
+ * From spc4r17 Section 5.7.9: Reserving:
+ *
+ * An application client creates a persistent reservation by issuing
+ * a PERSISTENT RESERVE OUT command with RESERVE service action through
+ * a registered I_T nexus with the following parameters:
+ * a) RESERVATION KEY set to the value of the reservation key that is
+ * registered with the logical unit for the I_T nexus; and
+ */
+ if (res_key != pr_reg->pr_res_key) {
+ printk(KERN_ERR "SPC-3 PR RESERVE: Received res_key: 0x%016Lx"
+ " does not match existing SA REGISTER res_key:"
+ " 0x%016Lx\n", res_key, pr_reg->pr_res_key);
+ return(PYX_TRANSPORT_RESERVATION_CONFLICT);
+ }
+ /*
+ * From spc4r17 Section 5.7.9: Reserving:
+ *
+ * From above:
+ * b) TYPE field and SCOPE field set to the persistent reservation
+ * being created.
+ *
+ * Only one persistent reservation is allowed at a time per logical unit
+ * and that persistent reservation has a scope of LU_SCOPE.
+ */
+ if (scope != PR_SCOPE_LU_SCOPE) {
+ printk(KERN_ERR "SPC-3 PR: Illegal SCOPE: 0x%02x\n", scope);
+ return(PYX_TRANSPORT_INVALID_PARAMETER_LIST);
+ }
+ /*
+ * See if we have an existing PR reservation holder pointer at
+ * se_device_t->dev_pr_res_holder in the form t10_pr_registration_t
+ * *pr_res_holder.
+ */
+ spin_lock(&dev->dev_reservation_lock);
+ if ((pr_res_holder = dev->dev_pr_res_holder)) {
+ /*
+ * From spc4r17 Section 5.7.9: Reserving:
+ *
+ * If the device server receives a PERSISTENT RESERVE OUT command
+ * from an I_T nexus other than a persistent reservation holder
+ * (see 5.7.10) that attempts to create a persistent reservation
+ * when a persistent reservation already exists for the logical
+ * unit, then the command shall be completed with
+ * RESERVATION CONFLICT status.
+ *
+ */
+ if (pr_res_holder != pr_reg) {
+ se_node_acl_t *pr_res_nacl = pr_res_holder->pr_reg_nacl;
+ printk(KERN_ERR "SPC-3 PR: Attempted RESERVE from"
+ " [%s]: %s while reservation already held by"
+ " [%s]: %s, returning RESERVATION_CONFLICT\n",
+ CMD_TFO(cmd)->get_fabric_name(),
+ se_sess->se_node_acl->initiatorname,
+ TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+ pr_res_holder->pr_reg_nacl->initiatorname);
+
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_RESERVATION_CONFLICT);
+ }
+ /*
+ * From spc4r17 Section 5.7.9: Reserving:
+ *
+ * If a persistent reservation holder attempts to modify the
+ * type or scope of an existing persistent reservation, the
+ * command shall be completed with RESERVATION CONFLICT status.
+ */
+ if ((pr_res_holder->pr_res_type != type) ||
+ (pr_res_holder->pr_res_scope != scope)) {
+ se_node_acl_t *pr_res_nacl = pr_res_holder->pr_reg_nacl;
+ printk(KERN_ERR "SPC-3 PR: Attempted RESERVE from"
+ " [%s]: %s trying to change TYPE and/or SCOPE,"
+ " while reservation already held by [%s]: %s,"
+ " returning RESERVATION_CONFLICT\n",
+ CMD_TFO(cmd)->get_fabric_name(),
+ se_sess->se_node_acl->initiatorname,
+ TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+ pr_res_holder->pr_reg_nacl->initiatorname);
+
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_RESERVATION_CONFLICT);
+ }
+ /*
+ * From spc4r17 Section 5.7.9: Reserving:
+ *
+ * If the device server receives a PERSISTENT RESERVE OUT command
+ * with RESERVE service action where the TYPE field and the SCOPE
+ * field contain the same values as the existing type and scope
+ * from a persistent reservation holder, it shall not make any
+ * change to the existing persistent reservation and shall
+ * completethe command with GOOD status.
+ */
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_SENT_TO_TRANSPORT);
+ }
+ /*
+ * Otherwise, our *pr_reg becomes the PR reservation holder for said
+ * TYPE/SCOPE. Also set the received scope and type in *pr_reg.
+ */
+ pr_reg->pr_res_scope = scope;
+ pr_reg->pr_res_type = type;
+ dev->dev_pr_res_holder = pr_reg;
+ /*
+ * See All Target Ports (ALL_TG_PT) bit in spcr17, section 6.14.3
+ * Basic PERSISTENT RESERVER OUT parameter list, page 290
+ */
+ if (!(pr_reg->pr_reg_all_tg_pt)) {
+ dev->dev_pr_tg_port_res_lun = pr_reg->pr_reg_lun_single_tg_pt;
+ }
+ printk("SPC-3 PR [%s] Service Action: RESERVE created new reservation"
+ " holder TYPE: %s ALL_TG_PT: %d\n",
+ CMD_TFO(cmd)->get_fabric_name(), core_scsi3_pr_dump_type(type),
+ (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
+ printk("SPC-3 PR [%s] RESERVE Node: %s\n", CMD_TFO(cmd)->get_fabric_name(),
+ se_sess->se_node_acl->initiatorname);
+ spin_unlock(&dev->dev_reservation_lock);
+
return(0);
}

+static int core_scsi3_pro_reserve_regonly (
+ se_cmd_t *cmd,
+ se_device_t *dev,
+ int type,
+ int scope,
+ u64 res_key)
+{
+ return(0);
+}
+
+static int core_scsi3_pro_reserve_allreg (
+ se_cmd_t *cmd,
+ se_device_t *dev,
+ int type,
+ int scope,
+ u64 res_key)
+{
+ return(0);
+}
+
+static int core_scsi3_emulate_pro_reserve (
+ se_cmd_t *cmd,
+ int type,
+ int scope,
+ u64 res_key)
+{
+ se_device_t *dev = cmd->se_dev;
+ int ret = 0;
+
+ switch (type) {
+ case PR_TYPE_WRITE_EXCLUSIVE:
+ ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key);
+ break;
+ case PR_TYPE_EXCLUSIVE_ACCESS:
+ ret = core_scsi3_pro_reserve(cmd, dev, type, scope, res_key);
+ break;
+#if 0
+ case PR_TYPE_WRITE_EXCLUSIVE_REGONLY:
+ ret = core_scsi3_pro_reserve_regonly(cmd, dev, type, scope, res_key);
+ break;
+ case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY:
+ ret = core_scsi3_pro_reserve_regonly(cmd, dev, type, scope, res_key);
+ break;
+ case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
+ ret = core_scsi3_pro_reserve_allreg(cmd, dev, type, scope, res_key);
+ break;
+ case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG:
+ ret = core_scsi3_pro_reserve_allreg(cmd, dev, type, scope, res_key);
+ break;
+#endif
+ default:
+ printk(KERN_ERR "SPC-3 PR: Unknown Service Action RESERVE Type:"
+ " 0x%02x\n", type);
+ return(PYX_TRANSPORT_INVALID_CDB_FIELD);
+ }
+
+ return(ret);
+}
+
static int core_scsi3_emulate_pro_release (
se_cmd_t *cmd,
int type,
int scope,
u64 res_key)
{
+ 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;
+
+ if (!(se_sess) || !(se_lun)) {
+ printk(KERN_ERR "SPC-3 PR: se_sess || se_lun_t is NULL!\n");
+ return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+ }
+ /*
+ * Locate the existing *pr_reg via se_node_acl_t pointers
+ */
+ pr_reg = core_scsi3_locate_pr_reg(dev, se_sess->se_node_acl);
+ if (!(pr_reg)) {
+ printk(KERN_ERR "SPC-3 PR: Unable to locate"
+ " PR_REGISTERED *pr_reg\n");
+ return(PYX_TRANSPORT_LOGICAL_UNIT_COMMUNICATION_FAILURE);
+ }
+ /*
+ * From spc4r17 Section 5.7.11.2 Releasing:
+ *
+ * If there is no persistent reservation or in response to a persistent
+ * reservation release request from a registered I_T nexus that is not a
+ * persistent reservation holder (see 5.7.10), the device server shall do the following:
+ * a) Not release the persistent reservation, if any;
+ * b) Not remove any registrations; and
+ * c) Complete the command with GOOD status.
+ */
+ spin_lock(&dev->dev_reservation_lock);
+ if (!(pr_res_holder = dev->dev_pr_res_holder)) {
+ /*
+ * No persistent reservation, return GOOD status.
+ */
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_SENT_TO_TRANSPORT);
+ }
+ if (pr_res_holder != pr_reg) {
+ /*
+ * Release request from a registered I_T nexus that is not a
+ * persistent reservation holder. return GOOD status.
+ */
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_SENT_TO_TRANSPORT);
+ }
+ /*
+ * From spc4r17 Section 5.7.11.2 Releasing:
+ *
+ * Only the persistent reservation holder (see 5.7.10) is allowed to
+ * release a persistent reservation.
+ *
+ * An application client releases the persistent reservation by issuing
+ * a PERSISTENT RESERVE OUT command with RELEASE service action through
+ * an I_T nexus that is a persistent reservation holder with the following
+ * parameters:
+ * a) RESERVATION KEY field set to the value of the reservation key that
+ * is registered with the logical unit for the I_T nexus;
+ */
+ if (res_key != pr_reg->pr_res_key) {
+ printk(KERN_ERR "SPC-3 PR RELEASE: Received res_key: 0x%016Lx"
+ " does not match existing SA REGISTER res_key:"
+ " 0x%016Lx\n", res_key, pr_reg->pr_res_key);
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_RESERVATION_CONFLICT);
+ }
+ /*
+ * From spc4r17 Section 5.7.11.2 Releasing and above:
+ *
+ * b) TYPE field and SCOPE field set to match the persistent
+ * reservation being released.
+ */
+ if ((pr_res_holder->pr_res_type != type) ||
+ (pr_res_holder->pr_res_scope != scope)) {
+ se_node_acl_t *pr_res_nacl = pr_res_holder->pr_reg_nacl;
+ printk(KERN_ERR "SPC-3 PR RELEASE: Attempted to release"
+ " reservation from [%s]: %s with different TYPE "
+ "and/or SCOPE while reservation already held by"
+ " [%s]: %s, returning RESERVATION_CONFLICT\n",
+ CMD_TFO(cmd)->get_fabric_name(),
+ se_sess->se_node_acl->initiatorname,
+ TPG_TFO(pr_res_nacl->se_tpg)->get_fabric_name(),
+ pr_res_holder->pr_reg_nacl->initiatorname);
+
+ spin_unlock(&dev->dev_reservation_lock);
+ return(PYX_TRANSPORT_RESERVATION_CONFLICT);
+ }
+ /*
+ * Go ahead and release the current PR reservation holder.
+ */
+ dev->dev_pr_res_holder = NULL;
+ /*
+ * If All Target Ports (ALL_TG_PT) bit == 0, clear the
+ * se_lun_t pointer as well..
+ */
+ if (!(pr_reg->pr_reg_all_tg_pt)) {
+ dev->dev_pr_tg_port_res_lun = NULL;
+ }
+ printk("SPC-3 PR [%s] Service Action: RELEASE cleared reservation holder"
+ " TYPE: %s ALL_TG_PT: %d\n", CMD_TFO(cmd)->get_fabric_name(),
+ core_scsi3_pr_dump_type(pr_reg->pr_res_type),
+ (pr_reg->pr_reg_all_tg_pt) ? 1 : 0);
+ printk("SPC-3 PR [%s] RELEASE Node: %s\n", CMD_TFO(cmd)->get_fabric_name(),
+ se_sess->se_node_acl->initiatorname);
+ /*
+ * Clear TYPE and SCOPE for the next PROUT Service Action: RESERVE
+ */
+ pr_reg->pr_res_type = pr_reg->pr_res_scope = 0;
+ spin_unlock(&dev->dev_reservation_lock);
+
return(0);
}

@@ -657,13 +991,13 @@ static int core_scsi3_emulate_pr_out (se_cmd_t *cmd, unsigned char *cdb)
case PRO_REGISTER:
return(core_scsi3_emulate_pro_register(cmd,
res_key, sa_res_key, aptpl, all_tg_pt, spec_i_pt));
-#if 0
case PRO_RESERVE:
return(core_scsi3_emulate_pro_reserve(cmd,
type, scope, res_key));
case PRO_RELEASE:
return(core_scsi3_emulate_pro_release(cmd,
type, scope, res_key));
+#if 0
case PRO_CLEAR:
return(core_scsi3_emulate_pro_clear(cmd,
res_key));
@@ -779,8 +1113,8 @@ static int core_scsi3_pri_read_reservation (se_cmd_t *cmd)
/*
* Set the SCOPE and TYPE
*/
- buf[21] = ((pr_reg->pr_res_type << 8) & 0xff) |
- (pr_reg->pr_res_scope & 0xff);
+ buf[21] = (pr_reg->pr_res_scope & 0xf0) |
+ (pr_reg->pr_res_type & 0x0f);
}
spin_unlock(&se_dev->dev_reservation_lock);

@@ -795,8 +1129,6 @@ static int core_scsi3_pri_read_reservation (se_cmd_t *cmd)
static int core_scsi3_pri_report_capabilities (se_cmd_t *cmd)
{
se_device_t *se_dev = SE_DEV(cmd);
- se_subsystem_dev_t *su_dev = SU_DEV(se_dev);
- t10_pr_registration_t *pr_reg;
unsigned char *buf = (unsigned char *)T_TASK(cmd)->t_task_buf;
u16 add_len = 8; /* Hardcoded to 8. */

@@ -807,7 +1139,7 @@ static int core_scsi3_pri_report_capabilities (se_cmd_t *cmd)
*/
// buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */
// buf[2] |= 0x08; /* SIP_C: Specify Initiator Ports Capable bit */
-// buf[2] |= 0x04; /* ATP_C: All Target Ports Capable bit */
+ buf[2] |= 0x04; /* ATP_C: All Target Ports Capable bit */
// buf[2] |= 0x01; /* PTPL_C: Persistence across Target Power Loss Capable bit */
/*
* We are filling in the PERSISTENT RESERVATION TYPE MASK below, so
diff --git a/drivers/lio-core/target_core_pr.h b/drivers/lio-core/target_core_pr.h
index 3a3d646..12802c1 100644
--- a/drivers/lio-core/target_core_pr.h
+++ b/drivers/lio-core/target_core_pr.h
@@ -39,5 +39,6 @@
#define PR_TYPE_EXCLUSIVE_ACCESS_ALLREG 0x08

extern void core_scsi3_free_all_registrations (struct se_device_s *);
+extern unsigned char *core_scsi3_pr_dump_type (int);
extern int core_scsi3_emulate_pr (struct se_cmd_s *);
extern int core_setup_reservations (struct se_device_s *);
--
1.5.4.1



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