|
@@ -35,7 +35,6 @@
|
|
|
#include <target/target_core_base.h>
|
|
#include <target/target_core_base.h>
|
|
|
#include <target/target_core_backend.h>
|
|
#include <target/target_core_backend.h>
|
|
|
#include <target/target_core_fabric.h>
|
|
#include <target/target_core_fabric.h>
|
|
|
-#include <target/target_core_configfs.h>
|
|
|
|
|
|
|
|
|
|
#include "target_core_internal.h"
|
|
#include "target_core_internal.h"
|
|
|
#include "target_core_pr.h"
|
|
#include "target_core_pr.h"
|
|
@@ -45,7 +44,6 @@
|
|
|
* Used for Specify Initiator Ports Capable Bit (SPEC_I_PT)
|
|
* Used for Specify Initiator Ports Capable Bit (SPEC_I_PT)
|
|
|
*/
|
|
*/
|
|
|
struct pr_transport_id_holder {
|
|
struct pr_transport_id_holder {
|
|
|
- int dest_local_nexus;
|
|
|
|
|
struct t10_pr_registration *dest_pr_reg;
|
|
struct t10_pr_registration *dest_pr_reg;
|
|
|
struct se_portal_group *dest_tpg;
|
|
struct se_portal_group *dest_tpg;
|
|
|
struct se_node_acl *dest_node_acl;
|
|
struct se_node_acl *dest_node_acl;
|
|
@@ -231,9 +229,10 @@ target_scsi2_reservation_release(struct se_cmd *cmd)
|
|
|
dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID;
|
|
dev->dev_reservation_flags &= ~DRF_SPC2_RESERVATIONS_WITH_ISID;
|
|
|
}
|
|
}
|
|
|
tpg = sess->se_tpg;
|
|
tpg = sess->se_tpg;
|
|
|
- pr_debug("SCSI-2 Released reservation for %s LUN: %u ->"
|
|
|
|
|
- " MAPPED LUN: %u for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
|
|
- cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun,
|
|
|
|
|
|
|
+ pr_debug("SCSI-2 Released reservation for %s LUN: %llu ->"
|
|
|
|
|
+ " MAPPED LUN: %llu for %s\n",
|
|
|
|
|
+ tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
|
|
+ cmd->se_lun->unpacked_lun, cmd->orig_fe_lun,
|
|
|
sess->se_node_acl->initiatorname);
|
|
sess->se_node_acl->initiatorname);
|
|
|
|
|
|
|
|
out_unlock:
|
|
out_unlock:
|
|
@@ -277,12 +276,12 @@ target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
(dev->dev_reserved_node_acl != sess->se_node_acl)) {
|
|
(dev->dev_reserved_node_acl != sess->se_node_acl)) {
|
|
|
pr_err("SCSI-2 RESERVATION CONFLIFT for %s fabric\n",
|
|
pr_err("SCSI-2 RESERVATION CONFLIFT for %s fabric\n",
|
|
|
tpg->se_tpg_tfo->get_fabric_name());
|
|
tpg->se_tpg_tfo->get_fabric_name());
|
|
|
- pr_err("Original reserver LUN: %u %s\n",
|
|
|
|
|
|
|
+ pr_err("Original reserver LUN: %llu %s\n",
|
|
|
cmd->se_lun->unpacked_lun,
|
|
cmd->se_lun->unpacked_lun,
|
|
|
dev->dev_reserved_node_acl->initiatorname);
|
|
dev->dev_reserved_node_acl->initiatorname);
|
|
|
- pr_err("Current attempt - LUN: %u -> MAPPED LUN: %u"
|
|
|
|
|
|
|
+ pr_err("Current attempt - LUN: %llu -> MAPPED LUN: %llu"
|
|
|
" from %s \n", cmd->se_lun->unpacked_lun,
|
|
" from %s \n", cmd->se_lun->unpacked_lun,
|
|
|
- cmd->se_deve->mapped_lun,
|
|
|
|
|
|
|
+ cmd->orig_fe_lun,
|
|
|
sess->se_node_acl->initiatorname);
|
|
sess->se_node_acl->initiatorname);
|
|
|
ret = TCM_RESERVATION_CONFLICT;
|
|
ret = TCM_RESERVATION_CONFLICT;
|
|
|
goto out_unlock;
|
|
goto out_unlock;
|
|
@@ -294,9 +293,9 @@ target_scsi2_reservation_reserve(struct se_cmd *cmd)
|
|
|
dev->dev_res_bin_isid = sess->sess_bin_isid;
|
|
dev->dev_res_bin_isid = sess->sess_bin_isid;
|
|
|
dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID;
|
|
dev->dev_reservation_flags |= DRF_SPC2_RESERVATIONS_WITH_ISID;
|
|
|
}
|
|
}
|
|
|
- pr_debug("SCSI-2 Reserved %s LUN: %u -> MAPPED LUN: %u"
|
|
|
|
|
|
|
+ pr_debug("SCSI-2 Reserved %s LUN: %llu -> MAPPED LUN: %llu"
|
|
|
" for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
|
|
" for %s\n", tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
- cmd->se_lun->unpacked_lun, cmd->se_deve->mapped_lun,
|
|
|
|
|
|
|
+ cmd->se_lun->unpacked_lun, cmd->orig_fe_lun,
|
|
|
sess->se_node_acl->initiatorname);
|
|
sess->se_node_acl->initiatorname);
|
|
|
|
|
|
|
|
out_unlock:
|
|
out_unlock:
|
|
@@ -314,28 +313,31 @@ out:
|
|
|
* This function is called by those initiator ports who are *NOT*
|
|
* This function is called by those initiator ports who are *NOT*
|
|
|
* the active PR reservation holder when a reservation is present.
|
|
* the active PR reservation holder when a reservation is present.
|
|
|
*/
|
|
*/
|
|
|
-static int core_scsi3_pr_seq_non_holder(
|
|
|
|
|
- struct se_cmd *cmd,
|
|
|
|
|
- u32 pr_reg_type)
|
|
|
|
|
|
|
+static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type,
|
|
|
|
|
+ bool isid_mismatch)
|
|
|
{
|
|
{
|
|
|
unsigned char *cdb = cmd->t_task_cdb;
|
|
unsigned char *cdb = cmd->t_task_cdb;
|
|
|
- struct se_dev_entry *se_deve;
|
|
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
- int other_cdb = 0, ignore_reg;
|
|
|
|
|
|
|
+ struct se_node_acl *nacl = se_sess->se_node_acl;
|
|
|
|
|
+ int other_cdb = 0;
|
|
|
int registered_nexus = 0, ret = 1; /* Conflict by default */
|
|
int registered_nexus = 0, ret = 1; /* Conflict by default */
|
|
|
int all_reg = 0, reg_only = 0; /* ALL_REG, REG_ONLY */
|
|
int all_reg = 0, reg_only = 0; /* ALL_REG, REG_ONLY */
|
|
|
int we = 0; /* Write Exclusive */
|
|
int we = 0; /* Write Exclusive */
|
|
|
int legacy = 0; /* Act like a legacy device and return
|
|
int legacy = 0; /* Act like a legacy device and return
|
|
|
* RESERVATION CONFLICT on some CDBs */
|
|
* RESERVATION CONFLICT on some CDBs */
|
|
|
|
|
|
|
|
- se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
|
|
|
|
|
- /*
|
|
|
|
|
- * Determine if the registration should be ignored due to
|
|
|
|
|
- * non-matching ISIDs in target_scsi3_pr_reservation_check().
|
|
|
|
|
- */
|
|
|
|
|
- ignore_reg = (pr_reg_type & 0x80000000);
|
|
|
|
|
- if (ignore_reg)
|
|
|
|
|
- pr_reg_type &= ~0x80000000;
|
|
|
|
|
|
|
+ if (isid_mismatch) {
|
|
|
|
|
+ registered_nexus = 0;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ struct se_dev_entry *se_deve;
|
|
|
|
|
+
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
+ se_deve = target_nacl_find_deve(nacl, cmd->orig_fe_lun);
|
|
|
|
|
+ if (se_deve)
|
|
|
|
|
+ registered_nexus = test_bit(DEF_PR_REG_ACTIVE,
|
|
|
|
|
+ &se_deve->deve_flags);
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
switch (pr_reg_type) {
|
|
switch (pr_reg_type) {
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE:
|
|
case PR_TYPE_WRITE_EXCLUSIVE:
|
|
@@ -345,8 +347,6 @@ static int core_scsi3_pr_seq_non_holder(
|
|
|
* Some commands are only allowed for the persistent reservation
|
|
* Some commands are only allowed for the persistent reservation
|
|
|
* holder.
|
|
* holder.
|
|
|
*/
|
|
*/
|
|
|
- if ((se_deve->def_pr_registered) && !(ignore_reg))
|
|
|
|
|
- registered_nexus = 1;
|
|
|
|
|
break;
|
|
break;
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE_REGONLY:
|
|
case PR_TYPE_WRITE_EXCLUSIVE_REGONLY:
|
|
|
we = 1;
|
|
we = 1;
|
|
@@ -355,8 +355,6 @@ static int core_scsi3_pr_seq_non_holder(
|
|
|
* Some commands are only allowed for registered I_T Nexuses.
|
|
* Some commands are only allowed for registered I_T Nexuses.
|
|
|
*/
|
|
*/
|
|
|
reg_only = 1;
|
|
reg_only = 1;
|
|
|
- if ((se_deve->def_pr_registered) && !(ignore_reg))
|
|
|
|
|
- registered_nexus = 1;
|
|
|
|
|
break;
|
|
break;
|
|
|
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
|
|
case PR_TYPE_WRITE_EXCLUSIVE_ALLREG:
|
|
|
we = 1;
|
|
we = 1;
|
|
@@ -365,8 +363,6 @@ static int core_scsi3_pr_seq_non_holder(
|
|
|
* Each registered I_T Nexus is a reservation holder.
|
|
* Each registered I_T Nexus is a reservation holder.
|
|
|
*/
|
|
*/
|
|
|
all_reg = 1;
|
|
all_reg = 1;
|
|
|
- if ((se_deve->def_pr_registered) && !(ignore_reg))
|
|
|
|
|
- registered_nexus = 1;
|
|
|
|
|
break;
|
|
break;
|
|
|
default:
|
|
default:
|
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
@@ -572,6 +568,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_session *sess = cmd->se_sess;
|
|
struct se_session *sess = cmd->se_sess;
|
|
|
u32 pr_reg_type;
|
|
u32 pr_reg_type;
|
|
|
|
|
+ bool isid_mismatch = false;
|
|
|
|
|
|
|
|
if (!dev->dev_pr_res_holder)
|
|
if (!dev->dev_pr_res_holder)
|
|
|
return 0;
|
|
return 0;
|
|
@@ -584,7 +581,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
if (dev->dev_pr_res_holder->isid_present_at_reg) {
|
|
if (dev->dev_pr_res_holder->isid_present_at_reg) {
|
|
|
if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
|
|
if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
|
|
|
sess->sess_bin_isid) {
|
|
sess->sess_bin_isid) {
|
|
|
- pr_reg_type |= 0x80000000;
|
|
|
|
|
|
|
+ isid_mismatch = true;
|
|
|
goto check_nonholder;
|
|
goto check_nonholder;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -592,7 +589,7 @@ target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
check_nonholder:
|
|
check_nonholder:
|
|
|
- if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
|
|
|
|
|
|
|
+ if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type, isid_mismatch))
|
|
|
return TCM_RESERVATION_CONFLICT;
|
|
return TCM_RESERVATION_CONFLICT;
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -620,7 +617,9 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
|
|
|
static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
|
|
static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
|
|
|
struct se_device *dev,
|
|
struct se_device *dev,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
|
|
|
+ struct se_lun *lun,
|
|
|
struct se_dev_entry *deve,
|
|
struct se_dev_entry *deve,
|
|
|
|
|
+ u64 mapped_lun,
|
|
|
unsigned char *isid,
|
|
unsigned char *isid,
|
|
|
u64 sa_res_key,
|
|
u64 sa_res_key,
|
|
|
int all_tg_pt,
|
|
int all_tg_pt,
|
|
@@ -642,12 +641,12 @@ static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
|
|
|
atomic_set(&pr_reg->pr_res_holders, 0);
|
|
atomic_set(&pr_reg->pr_res_holders, 0);
|
|
|
pr_reg->pr_reg_nacl = nacl;
|
|
pr_reg->pr_reg_nacl = nacl;
|
|
|
pr_reg->pr_reg_deve = deve;
|
|
pr_reg->pr_reg_deve = deve;
|
|
|
- pr_reg->pr_res_mapped_lun = deve->mapped_lun;
|
|
|
|
|
- pr_reg->pr_aptpl_target_lun = deve->se_lun->unpacked_lun;
|
|
|
|
|
|
|
+ pr_reg->pr_res_mapped_lun = mapped_lun;
|
|
|
|
|
+ pr_reg->pr_aptpl_target_lun = lun->unpacked_lun;
|
|
|
|
|
+ pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
|
|
|
pr_reg->pr_res_key = sa_res_key;
|
|
pr_reg->pr_res_key = sa_res_key;
|
|
|
pr_reg->pr_reg_all_tg_pt = all_tg_pt;
|
|
pr_reg->pr_reg_all_tg_pt = all_tg_pt;
|
|
|
pr_reg->pr_reg_aptpl = aptpl;
|
|
pr_reg->pr_reg_aptpl = aptpl;
|
|
|
- pr_reg->pr_reg_tg_pt_lun = deve->se_lun;
|
|
|
|
|
/*
|
|
/*
|
|
|
* If an ISID value for this SCSI Initiator Port exists,
|
|
* If an ISID value for this SCSI Initiator Port exists,
|
|
|
* save it to the registration now.
|
|
* save it to the registration now.
|
|
@@ -671,7 +670,9 @@ static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *);
|
|
|
static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
struct se_device *dev,
|
|
struct se_device *dev,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
|
|
|
+ struct se_lun *lun,
|
|
|
struct se_dev_entry *deve,
|
|
struct se_dev_entry *deve,
|
|
|
|
|
+ u64 mapped_lun,
|
|
|
unsigned char *isid,
|
|
unsigned char *isid,
|
|
|
u64 sa_res_key,
|
|
u64 sa_res_key,
|
|
|
int all_tg_pt,
|
|
int all_tg_pt,
|
|
@@ -679,7 +680,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
{
|
|
{
|
|
|
struct se_dev_entry *deve_tmp;
|
|
struct se_dev_entry *deve_tmp;
|
|
|
struct se_node_acl *nacl_tmp;
|
|
struct se_node_acl *nacl_tmp;
|
|
|
- struct se_port *port, *port_tmp;
|
|
|
|
|
|
|
+ struct se_lun_acl *lacl_tmp;
|
|
|
|
|
+ struct se_lun *lun_tmp, *next, *dest_lun;
|
|
|
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
|
|
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_atp, *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
|
int ret;
|
|
int ret;
|
|
@@ -687,8 +689,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
* Create a registration for the I_T Nexus upon which the
|
|
* Create a registration for the I_T Nexus upon which the
|
|
|
* PROUT REGISTER was received.
|
|
* PROUT REGISTER was received.
|
|
|
*/
|
|
*/
|
|
|
- pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, deve, isid,
|
|
|
|
|
- sa_res_key, all_tg_pt, aptpl);
|
|
|
|
|
|
|
+ pr_reg = __core_scsi3_do_alloc_registration(dev, nacl, lun, deve, mapped_lun,
|
|
|
|
|
+ isid, sa_res_key, all_tg_pt,
|
|
|
|
|
+ aptpl);
|
|
|
if (!pr_reg)
|
|
if (!pr_reg)
|
|
|
return NULL;
|
|
return NULL;
|
|
|
/*
|
|
/*
|
|
@@ -701,13 +704,13 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
* for ALL_TG_PT=1
|
|
* for ALL_TG_PT=1
|
|
|
*/
|
|
*/
|
|
|
spin_lock(&dev->se_port_lock);
|
|
spin_lock(&dev->se_port_lock);
|
|
|
- list_for_each_entry_safe(port, port_tmp, &dev->dev_sep_list, sep_list) {
|
|
|
|
|
- atomic_inc_mb(&port->sep_tg_pt_ref_cnt);
|
|
|
|
|
|
|
+ list_for_each_entry_safe(lun_tmp, next, &dev->dev_sep_list, lun_dev_link) {
|
|
|
|
|
+ if (!percpu_ref_tryget_live(&lun_tmp->lun_ref))
|
|
|
|
|
+ continue;
|
|
|
spin_unlock(&dev->se_port_lock);
|
|
spin_unlock(&dev->se_port_lock);
|
|
|
|
|
|
|
|
- spin_lock_bh(&port->sep_alua_lock);
|
|
|
|
|
- list_for_each_entry(deve_tmp, &port->sep_alua_list,
|
|
|
|
|
- alua_port_list) {
|
|
|
|
|
|
|
+ spin_lock(&lun_tmp->lun_deve_lock);
|
|
|
|
|
+ list_for_each_entry(deve_tmp, &lun_tmp->lun_deve_list, lun_link) {
|
|
|
/*
|
|
/*
|
|
|
* This pointer will be NULL for demo mode MappedLUNs
|
|
* This pointer will be NULL for demo mode MappedLUNs
|
|
|
* that have not been make explicit via a ConfigFS
|
|
* that have not been make explicit via a ConfigFS
|
|
@@ -716,7 +719,9 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
if (!deve_tmp->se_lun_acl)
|
|
if (!deve_tmp->se_lun_acl)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- nacl_tmp = deve_tmp->se_lun_acl->se_lun_nacl;
|
|
|
|
|
|
|
+ lacl_tmp = rcu_dereference_check(deve_tmp->se_lun_acl,
|
|
|
|
|
+ lockdep_is_held(&lun_tmp->lun_deve_lock));
|
|
|
|
|
+ nacl_tmp = lacl_tmp->se_lun_nacl;
|
|
|
/*
|
|
/*
|
|
|
* Skip the matching struct se_node_acl that is allocated
|
|
* Skip the matching struct se_node_acl that is allocated
|
|
|
* above..
|
|
* above..
|
|
@@ -736,8 +741,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
if (strcmp(nacl->initiatorname, nacl_tmp->initiatorname))
|
|
if (strcmp(nacl->initiatorname, nacl_tmp->initiatorname))
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- atomic_inc_mb(&deve_tmp->pr_ref_count);
|
|
|
|
|
- spin_unlock_bh(&port->sep_alua_lock);
|
|
|
|
|
|
|
+ kref_get(&deve_tmp->pr_kref);
|
|
|
|
|
+ spin_unlock(&lun_tmp->lun_deve_lock);
|
|
|
/*
|
|
/*
|
|
|
* Grab a configfs group dependency that is released
|
|
* Grab a configfs group dependency that is released
|
|
|
* for the exception path at label out: below, or upon
|
|
* for the exception path at label out: below, or upon
|
|
@@ -748,8 +753,8 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
|
pr_err("core_scsi3_lunacl_depend"
|
|
pr_err("core_scsi3_lunacl_depend"
|
|
|
"_item() failed\n");
|
|
"_item() failed\n");
|
|
|
- atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
|
|
|
|
|
- atomic_dec_mb(&deve_tmp->pr_ref_count);
|
|
|
|
|
|
|
+ percpu_ref_put(&lun_tmp->lun_ref);
|
|
|
|
|
+ kref_put(&deve_tmp->pr_kref, target_pr_kref_release);
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
/*
|
|
/*
|
|
@@ -759,24 +764,27 @@ static struct t10_pr_registration *__core_scsi3_alloc_registration(
|
|
|
* the original *pr_reg is processed in
|
|
* the original *pr_reg is processed in
|
|
|
* __core_scsi3_add_registration()
|
|
* __core_scsi3_add_registration()
|
|
|
*/
|
|
*/
|
|
|
|
|
+ dest_lun = rcu_dereference_check(deve_tmp->se_lun,
|
|
|
|
|
+ atomic_read(&deve_tmp->pr_kref.refcount) != 0);
|
|
|
|
|
+
|
|
|
pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
|
|
pr_reg_atp = __core_scsi3_do_alloc_registration(dev,
|
|
|
- nacl_tmp, deve_tmp, NULL,
|
|
|
|
|
|
|
+ nacl_tmp, dest_lun, deve_tmp,
|
|
|
|
|
+ deve_tmp->mapped_lun, NULL,
|
|
|
sa_res_key, all_tg_pt, aptpl);
|
|
sa_res_key, all_tg_pt, aptpl);
|
|
|
if (!pr_reg_atp) {
|
|
if (!pr_reg_atp) {
|
|
|
- atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
|
|
|
|
|
- atomic_dec_mb(&deve_tmp->pr_ref_count);
|
|
|
|
|
|
|
+ percpu_ref_put(&lun_tmp->lun_ref);
|
|
|
core_scsi3_lunacl_undepend_item(deve_tmp);
|
|
core_scsi3_lunacl_undepend_item(deve_tmp);
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
list_add_tail(&pr_reg_atp->pr_reg_atp_mem_list,
|
|
list_add_tail(&pr_reg_atp->pr_reg_atp_mem_list,
|
|
|
&pr_reg->pr_reg_atp_list);
|
|
&pr_reg->pr_reg_atp_list);
|
|
|
- spin_lock_bh(&port->sep_alua_lock);
|
|
|
|
|
|
|
+ spin_lock(&lun_tmp->lun_deve_lock);
|
|
|
}
|
|
}
|
|
|
- spin_unlock_bh(&port->sep_alua_lock);
|
|
|
|
|
|
|
+ spin_unlock(&lun_tmp->lun_deve_lock);
|
|
|
|
|
|
|
|
spin_lock(&dev->se_port_lock);
|
|
spin_lock(&dev->se_port_lock);
|
|
|
- atomic_dec_mb(&port->sep_tg_pt_ref_cnt);
|
|
|
|
|
|
|
+ percpu_ref_put(&lun_tmp->lun_ref);
|
|
|
}
|
|
}
|
|
|
spin_unlock(&dev->se_port_lock);
|
|
spin_unlock(&dev->se_port_lock);
|
|
|
|
|
|
|
@@ -797,10 +805,10 @@ int core_scsi3_alloc_aptpl_registration(
|
|
|
u64 sa_res_key,
|
|
u64 sa_res_key,
|
|
|
unsigned char *i_port,
|
|
unsigned char *i_port,
|
|
|
unsigned char *isid,
|
|
unsigned char *isid,
|
|
|
- u32 mapped_lun,
|
|
|
|
|
|
|
+ u64 mapped_lun,
|
|
|
unsigned char *t_port,
|
|
unsigned char *t_port,
|
|
|
u16 tpgt,
|
|
u16 tpgt,
|
|
|
- u32 target_lun,
|
|
|
|
|
|
|
+ u64 target_lun,
|
|
|
int res_holder,
|
|
int res_holder,
|
|
|
int all_tg_pt,
|
|
int all_tg_pt,
|
|
|
u8 type)
|
|
u8 type)
|
|
@@ -831,7 +839,6 @@ int core_scsi3_alloc_aptpl_registration(
|
|
|
pr_reg->pr_res_key = sa_res_key;
|
|
pr_reg->pr_res_key = sa_res_key;
|
|
|
pr_reg->pr_reg_all_tg_pt = all_tg_pt;
|
|
pr_reg->pr_reg_all_tg_pt = all_tg_pt;
|
|
|
pr_reg->pr_reg_aptpl = 1;
|
|
pr_reg->pr_reg_aptpl = 1;
|
|
|
- pr_reg->pr_reg_tg_pt_lun = NULL;
|
|
|
|
|
pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */
|
|
pr_reg->pr_res_scope = 0; /* Always LUN_SCOPE */
|
|
|
pr_reg->pr_res_type = type;
|
|
pr_reg->pr_res_type = type;
|
|
|
/*
|
|
/*
|
|
@@ -895,9 +902,9 @@ static int __core_scsi3_check_aptpl_registration(
|
|
|
struct se_device *dev,
|
|
struct se_device *dev,
|
|
|
struct se_portal_group *tpg,
|
|
struct se_portal_group *tpg,
|
|
|
struct se_lun *lun,
|
|
struct se_lun *lun,
|
|
|
- u32 target_lun,
|
|
|
|
|
|
|
+ u64 target_lun,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
|
- struct se_dev_entry *deve)
|
|
|
|
|
|
|
+ u64 mapped_lun)
|
|
|
{
|
|
{
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
@@ -925,14 +932,13 @@ static int __core_scsi3_check_aptpl_registration(
|
|
|
pr_reg_aptpl_list) {
|
|
pr_reg_aptpl_list) {
|
|
|
|
|
|
|
|
if (!strcmp(pr_reg->pr_iport, i_port) &&
|
|
if (!strcmp(pr_reg->pr_iport, i_port) &&
|
|
|
- (pr_reg->pr_res_mapped_lun == deve->mapped_lun) &&
|
|
|
|
|
|
|
+ (pr_reg->pr_res_mapped_lun == mapped_lun) &&
|
|
|
!(strcmp(pr_reg->pr_tport, t_port)) &&
|
|
!(strcmp(pr_reg->pr_tport, t_port)) &&
|
|
|
(pr_reg->pr_reg_tpgt == tpgt) &&
|
|
(pr_reg->pr_reg_tpgt == tpgt) &&
|
|
|
(pr_reg->pr_aptpl_target_lun == target_lun)) {
|
|
(pr_reg->pr_aptpl_target_lun == target_lun)) {
|
|
|
|
|
|
|
|
pr_reg->pr_reg_nacl = nacl;
|
|
pr_reg->pr_reg_nacl = nacl;
|
|
|
- pr_reg->pr_reg_deve = deve;
|
|
|
|
|
- pr_reg->pr_reg_tg_pt_lun = lun;
|
|
|
|
|
|
|
+ pr_reg->tg_pt_sep_rtpi = lun->lun_rtpi;
|
|
|
|
|
|
|
|
list_del(&pr_reg->pr_reg_aptpl_list);
|
|
list_del(&pr_reg->pr_reg_aptpl_list);
|
|
|
spin_unlock(&pr_tmpl->aptpl_reg_lock);
|
|
spin_unlock(&pr_tmpl->aptpl_reg_lock);
|
|
@@ -967,15 +973,14 @@ int core_scsi3_check_aptpl_registration(
|
|
|
struct se_portal_group *tpg,
|
|
struct se_portal_group *tpg,
|
|
|
struct se_lun *lun,
|
|
struct se_lun *lun,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
|
- u32 mapped_lun)
|
|
|
|
|
|
|
+ u64 mapped_lun)
|
|
|
{
|
|
{
|
|
|
- struct se_dev_entry *deve = nacl->device_list[mapped_lun];
|
|
|
|
|
-
|
|
|
|
|
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
|
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
|
return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
|
|
return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
|
|
|
- lun->unpacked_lun, nacl, deve);
|
|
|
|
|
|
|
+ lun->unpacked_lun, nacl,
|
|
|
|
|
+ mapped_lun);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void __core_scsi3_dump_registration(
|
|
static void __core_scsi3_dump_registration(
|
|
@@ -1009,10 +1014,6 @@ static void __core_scsi3_dump_registration(
|
|
|
pr_reg->pr_reg_aptpl);
|
|
pr_reg->pr_reg_aptpl);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/*
|
|
|
|
|
- * this function can be called with struct se_device->dev_reservation_lock
|
|
|
|
|
- * when register_move = 1
|
|
|
|
|
- */
|
|
|
|
|
static void __core_scsi3_add_registration(
|
|
static void __core_scsi3_add_registration(
|
|
|
struct se_device *dev,
|
|
struct se_device *dev,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
@@ -1023,6 +1024,7 @@ static void __core_scsi3_add_registration(
|
|
|
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
|
|
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
|
|
|
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
|
|
+ struct se_dev_entry *deve;
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
* Increment PRgeneration counter for struct se_device upon a successful
|
|
* Increment PRgeneration counter for struct se_device upon a successful
|
|
@@ -1039,10 +1041,16 @@ static void __core_scsi3_add_registration(
|
|
|
|
|
|
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
|
list_add_tail(&pr_reg->pr_reg_list, &pr_tmpl->registration_list);
|
|
list_add_tail(&pr_reg->pr_reg_list, &pr_tmpl->registration_list);
|
|
|
- pr_reg->pr_reg_deve->def_pr_registered = 1;
|
|
|
|
|
|
|
|
|
|
__core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
|
|
__core_scsi3_dump_registration(tfo, dev, nacl, pr_reg, register_type);
|
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
|
|
|
+
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
+ deve = pr_reg->pr_reg_deve;
|
|
|
|
|
+ if (deve)
|
|
|
|
|
+ set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
|
|
* Skip extra processing for ALL_TG_PT=0 or REGISTER_AND_MOVE.
|
|
|
*/
|
|
*/
|
|
@@ -1054,6 +1062,8 @@ static void __core_scsi3_add_registration(
|
|
|
*/
|
|
*/
|
|
|
list_for_each_entry_safe(pr_reg_tmp, pr_reg_tmp_safe,
|
|
list_for_each_entry_safe(pr_reg_tmp, pr_reg_tmp_safe,
|
|
|
&pr_reg->pr_reg_atp_list, pr_reg_atp_mem_list) {
|
|
&pr_reg->pr_reg_atp_list, pr_reg_atp_mem_list) {
|
|
|
|
|
+ struct se_node_acl *nacl_tmp = pr_reg_tmp->pr_reg_nacl;
|
|
|
|
|
+
|
|
|
list_del(&pr_reg_tmp->pr_reg_atp_mem_list);
|
|
list_del(&pr_reg_tmp->pr_reg_atp_mem_list);
|
|
|
|
|
|
|
|
pr_reg_tmp->pr_res_generation = core_scsi3_pr_generation(dev);
|
|
pr_reg_tmp->pr_res_generation = core_scsi3_pr_generation(dev);
|
|
@@ -1061,12 +1071,17 @@ static void __core_scsi3_add_registration(
|
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
|
list_add_tail(&pr_reg_tmp->pr_reg_list,
|
|
list_add_tail(&pr_reg_tmp->pr_reg_list,
|
|
|
&pr_tmpl->registration_list);
|
|
&pr_tmpl->registration_list);
|
|
|
- pr_reg_tmp->pr_reg_deve->def_pr_registered = 1;
|
|
|
|
|
|
|
|
|
|
- __core_scsi3_dump_registration(tfo, dev,
|
|
|
|
|
- pr_reg_tmp->pr_reg_nacl, pr_reg_tmp,
|
|
|
|
|
- register_type);
|
|
|
|
|
|
|
+ __core_scsi3_dump_registration(tfo, dev, nacl_tmp, pr_reg_tmp,
|
|
|
|
|
+ register_type);
|
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
|
|
|
+
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
+ deve = pr_reg_tmp->pr_reg_deve;
|
|
|
|
|
+ if (deve)
|
|
|
|
|
+ set_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Drop configfs group dependency reference from
|
|
* Drop configfs group dependency reference from
|
|
|
* __core_scsi3_alloc_registration()
|
|
* __core_scsi3_alloc_registration()
|
|
@@ -1078,7 +1093,9 @@ static void __core_scsi3_add_registration(
|
|
|
static int core_scsi3_alloc_registration(
|
|
static int core_scsi3_alloc_registration(
|
|
|
struct se_device *dev,
|
|
struct se_device *dev,
|
|
|
struct se_node_acl *nacl,
|
|
struct se_node_acl *nacl,
|
|
|
|
|
+ struct se_lun *lun,
|
|
|
struct se_dev_entry *deve,
|
|
struct se_dev_entry *deve,
|
|
|
|
|
+ u64 mapped_lun,
|
|
|
unsigned char *isid,
|
|
unsigned char *isid,
|
|
|
u64 sa_res_key,
|
|
u64 sa_res_key,
|
|
|
int all_tg_pt,
|
|
int all_tg_pt,
|
|
@@ -1088,8 +1105,9 @@ static int core_scsi3_alloc_registration(
|
|
|
{
|
|
{
|
|
|
struct t10_pr_registration *pr_reg;
|
|
struct t10_pr_registration *pr_reg;
|
|
|
|
|
|
|
|
- pr_reg = __core_scsi3_alloc_registration(dev, nacl, deve, isid,
|
|
|
|
|
- sa_res_key, all_tg_pt, aptpl);
|
|
|
|
|
|
|
+ pr_reg = __core_scsi3_alloc_registration(dev, nacl, lun, deve, mapped_lun,
|
|
|
|
|
+ isid, sa_res_key, all_tg_pt,
|
|
|
|
|
+ aptpl);
|
|
|
if (!pr_reg)
|
|
if (!pr_reg)
|
|
|
return -EPERM;
|
|
return -EPERM;
|
|
|
|
|
|
|
@@ -1242,13 +1260,13 @@ static void __core_scsi3_free_registration(
|
|
|
const struct target_core_fabric_ops *tfo =
|
|
const struct target_core_fabric_ops *tfo =
|
|
|
pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
|
|
pr_reg->pr_reg_nacl->se_tpg->se_tpg_tfo;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
|
|
+ struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
|
|
|
|
|
+ struct se_dev_entry *deve;
|
|
|
char i_buf[PR_REG_ISID_ID_LEN];
|
|
char i_buf[PR_REG_ISID_ID_LEN];
|
|
|
|
|
|
|
|
memset(i_buf, 0, PR_REG_ISID_ID_LEN);
|
|
memset(i_buf, 0, PR_REG_ISID_ID_LEN);
|
|
|
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
|
|
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
|
|
|
|
|
|
|
|
- pr_reg->pr_reg_deve->def_pr_registered = 0;
|
|
|
|
|
- pr_reg->pr_reg_deve->pr_res_key = 0;
|
|
|
|
|
if (!list_empty(&pr_reg->pr_reg_list))
|
|
if (!list_empty(&pr_reg->pr_reg_list))
|
|
|
list_del(&pr_reg->pr_reg_list);
|
|
list_del(&pr_reg->pr_reg_list);
|
|
|
/*
|
|
/*
|
|
@@ -1257,6 +1275,8 @@ static void __core_scsi3_free_registration(
|
|
|
*/
|
|
*/
|
|
|
if (dec_holders)
|
|
if (dec_holders)
|
|
|
core_scsi3_put_pr_reg(pr_reg);
|
|
core_scsi3_put_pr_reg(pr_reg);
|
|
|
|
|
+
|
|
|
|
|
+ spin_unlock(&pr_tmpl->registration_lock);
|
|
|
/*
|
|
/*
|
|
|
* Wait until all reference from any other I_T nexuses for this
|
|
* Wait until all reference from any other I_T nexuses for this
|
|
|
* *pr_reg have been released. Because list_del() is called above,
|
|
* *pr_reg have been released. Because list_del() is called above,
|
|
@@ -1264,13 +1284,18 @@ static void __core_scsi3_free_registration(
|
|
|
* count back to zero, and we release *pr_reg.
|
|
* count back to zero, and we release *pr_reg.
|
|
|
*/
|
|
*/
|
|
|
while (atomic_read(&pr_reg->pr_res_holders) != 0) {
|
|
while (atomic_read(&pr_reg->pr_res_holders) != 0) {
|
|
|
- spin_unlock(&pr_tmpl->registration_lock);
|
|
|
|
|
pr_debug("SPC-3 PR [%s] waiting for pr_res_holders\n",
|
|
pr_debug("SPC-3 PR [%s] waiting for pr_res_holders\n",
|
|
|
tfo->get_fabric_name());
|
|
tfo->get_fabric_name());
|
|
|
cpu_relax();
|
|
cpu_relax();
|
|
|
- spin_lock(&pr_tmpl->registration_lock);
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ rcu_read_lock();
|
|
|
|
|
+ deve = target_nacl_find_deve(nacl, pr_reg->pr_res_mapped_lun);
|
|
|
|
|
+ if (deve)
|
|
|
|
|
+ clear_bit(DEF_PR_REG_ACTIVE, &deve->deve_flags);
|
|
|
|
|
+ rcu_read_unlock();
|
|
|
|
|
+
|
|
|
|
|
+ spin_lock(&pr_tmpl->registration_lock);
|
|
|
pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
|
|
pr_debug("SPC-3 PR [%s] Service Action: UNREGISTER Initiator"
|
|
|
" Node: %s%s\n", tfo->get_fabric_name(),
|
|
" Node: %s%s\n", tfo->get_fabric_name(),
|
|
|
pr_reg->pr_reg_nacl->initiatorname,
|
|
pr_reg->pr_reg_nacl->initiatorname,
|
|
@@ -1392,12 +1417,14 @@ static void core_scsi3_nodeacl_undepend_item(struct se_node_acl *nacl)
|
|
|
|
|
|
|
|
static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
|
|
static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
|
|
|
{
|
|
{
|
|
|
- struct se_lun_acl *lun_acl = se_deve->se_lun_acl;
|
|
|
|
|
|
|
+ struct se_lun_acl *lun_acl;
|
|
|
struct se_node_acl *nacl;
|
|
struct se_node_acl *nacl;
|
|
|
struct se_portal_group *tpg;
|
|
struct se_portal_group *tpg;
|
|
|
/*
|
|
/*
|
|
|
* For nacl->dynamic_node_acl=1
|
|
* For nacl->dynamic_node_acl=1
|
|
|
*/
|
|
*/
|
|
|
|
|
+ lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
|
|
|
|
|
+ atomic_read(&se_deve->pr_kref.refcount) != 0);
|
|
|
if (!lun_acl)
|
|
if (!lun_acl)
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
|
@@ -1409,21 +1436,23 @@ static int core_scsi3_lunacl_depend_item(struct se_dev_entry *se_deve)
|
|
|
|
|
|
|
|
static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
|
|
static void core_scsi3_lunacl_undepend_item(struct se_dev_entry *se_deve)
|
|
|
{
|
|
{
|
|
|
- struct se_lun_acl *lun_acl = se_deve->se_lun_acl;
|
|
|
|
|
|
|
+ struct se_lun_acl *lun_acl;
|
|
|
struct se_node_acl *nacl;
|
|
struct se_node_acl *nacl;
|
|
|
struct se_portal_group *tpg;
|
|
struct se_portal_group *tpg;
|
|
|
/*
|
|
/*
|
|
|
* For nacl->dynamic_node_acl=1
|
|
* For nacl->dynamic_node_acl=1
|
|
|
*/
|
|
*/
|
|
|
|
|
+ lun_acl = rcu_dereference_check(se_deve->se_lun_acl,
|
|
|
|
|
+ atomic_read(&se_deve->pr_kref.refcount) != 0);
|
|
|
if (!lun_acl) {
|
|
if (!lun_acl) {
|
|
|
- atomic_dec_mb(&se_deve->pr_ref_count);
|
|
|
|
|
|
|
+ kref_put(&se_deve->pr_kref, target_pr_kref_release);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
nacl = lun_acl->se_lun_nacl;
|
|
nacl = lun_acl->se_lun_nacl;
|
|
|
tpg = nacl->se_tpg;
|
|
tpg = nacl->se_tpg;
|
|
|
|
|
|
|
|
target_undepend_item(&lun_acl->se_lun_group.cg_item);
|
|
target_undepend_item(&lun_acl->se_lun_group.cg_item);
|
|
|
- atomic_dec_mb(&se_deve->pr_ref_count);
|
|
|
|
|
|
|
+ kref_put(&se_deve->pr_kref, target_pr_kref_release);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static sense_reason_t
|
|
static sense_reason_t
|
|
@@ -1436,30 +1465,25 @@ core_scsi3_decode_spec_i_port(
|
|
|
int aptpl)
|
|
int aptpl)
|
|
|
{
|
|
{
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
- struct se_port *tmp_port;
|
|
|
|
|
struct se_portal_group *dest_tpg = NULL, *tmp_tpg;
|
|
struct se_portal_group *dest_tpg = NULL, *tmp_tpg;
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_node_acl *dest_node_acl = NULL;
|
|
struct se_node_acl *dest_node_acl = NULL;
|
|
|
- struct se_dev_entry *dest_se_deve = NULL, *local_se_deve;
|
|
|
|
|
|
|
+ struct se_dev_entry *dest_se_deve = NULL;
|
|
|
struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e;
|
|
struct t10_pr_registration *dest_pr_reg, *local_pr_reg, *pr_reg_e;
|
|
|
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
struct t10_pr_registration *pr_reg_tmp, *pr_reg_tmp_safe;
|
|
|
LIST_HEAD(tid_dest_list);
|
|
LIST_HEAD(tid_dest_list);
|
|
|
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
|
|
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
|
|
|
- const struct target_core_fabric_ops *tmp_tf_ops;
|
|
|
|
|
- unsigned char *buf;
|
|
|
|
|
- unsigned char *ptr, *i_str = NULL, proto_ident, tmp_proto_ident;
|
|
|
|
|
|
|
+ unsigned char *buf, *ptr, proto_ident;
|
|
|
|
|
+ const unsigned char *i_str;
|
|
|
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
|
|
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
|
|
|
sense_reason_t ret;
|
|
sense_reason_t ret;
|
|
|
u32 tpdl, tid_len = 0;
|
|
u32 tpdl, tid_len = 0;
|
|
|
- int dest_local_nexus;
|
|
|
|
|
u32 dest_rtpi = 0;
|
|
u32 dest_rtpi = 0;
|
|
|
|
|
|
|
|
- local_se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
|
|
|
|
|
/*
|
|
/*
|
|
|
* Allocate a struct pr_transport_id_holder and setup the
|
|
* Allocate a struct pr_transport_id_holder and setup the
|
|
|
- * local_node_acl and local_se_deve pointers and add to
|
|
|
|
|
- * struct list_head tid_dest_list for add registration
|
|
|
|
|
- * processing in the loop of tid_dest_list below.
|
|
|
|
|
|
|
+ * local_node_acl pointer and add to struct list_head tid_dest_list
|
|
|
|
|
+ * for add registration processing in the loop of tid_dest_list below.
|
|
|
*/
|
|
*/
|
|
|
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
|
|
tidh_new = kzalloc(sizeof(struct pr_transport_id_holder), GFP_KERNEL);
|
|
|
if (!tidh_new) {
|
|
if (!tidh_new) {
|
|
@@ -1469,10 +1493,10 @@ core_scsi3_decode_spec_i_port(
|
|
|
INIT_LIST_HEAD(&tidh_new->dest_list);
|
|
INIT_LIST_HEAD(&tidh_new->dest_list);
|
|
|
tidh_new->dest_tpg = tpg;
|
|
tidh_new->dest_tpg = tpg;
|
|
|
tidh_new->dest_node_acl = se_sess->se_node_acl;
|
|
tidh_new->dest_node_acl = se_sess->se_node_acl;
|
|
|
- tidh_new->dest_se_deve = local_se_deve;
|
|
|
|
|
|
|
|
|
|
local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
|
|
local_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
- se_sess->se_node_acl, local_se_deve, l_isid,
|
|
|
|
|
|
|
+ se_sess->se_node_acl, cmd->se_lun,
|
|
|
|
|
+ NULL, cmd->orig_fe_lun, l_isid,
|
|
|
sa_res_key, all_tg_pt, aptpl);
|
|
sa_res_key, all_tg_pt, aptpl);
|
|
|
if (!local_pr_reg) {
|
|
if (!local_pr_reg) {
|
|
|
kfree(tidh_new);
|
|
kfree(tidh_new);
|
|
@@ -1481,10 +1505,10 @@ core_scsi3_decode_spec_i_port(
|
|
|
tidh_new->dest_pr_reg = local_pr_reg;
|
|
tidh_new->dest_pr_reg = local_pr_reg;
|
|
|
/*
|
|
/*
|
|
|
* The local I_T nexus does not hold any configfs dependances,
|
|
* The local I_T nexus does not hold any configfs dependances,
|
|
|
- * so we set tid_h->dest_local_nexus=1 to prevent the
|
|
|
|
|
|
|
+ * so we set tidh_new->dest_se_deve to NULL to prevent the
|
|
|
* configfs_undepend_item() calls in the tid_dest_list loops below.
|
|
* configfs_undepend_item() calls in the tid_dest_list loops below.
|
|
|
*/
|
|
*/
|
|
|
- tidh_new->dest_local_nexus = 1;
|
|
|
|
|
|
|
+ tidh_new->dest_se_deve = NULL;
|
|
|
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
|
|
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
|
|
|
|
|
|
|
|
if (cmd->data_length < 28) {
|
|
if (cmd->data_length < 28) {
|
|
@@ -1525,32 +1549,25 @@ core_scsi3_decode_spec_i_port(
|
|
|
ptr = &buf[28];
|
|
ptr = &buf[28];
|
|
|
|
|
|
|
|
while (tpdl > 0) {
|
|
while (tpdl > 0) {
|
|
|
|
|
+ struct se_lun *dest_lun, *tmp_lun;
|
|
|
|
|
+
|
|
|
proto_ident = (ptr[0] & 0x0f);
|
|
proto_ident = (ptr[0] & 0x0f);
|
|
|
dest_tpg = NULL;
|
|
dest_tpg = NULL;
|
|
|
|
|
|
|
|
spin_lock(&dev->se_port_lock);
|
|
spin_lock(&dev->se_port_lock);
|
|
|
- list_for_each_entry(tmp_port, &dev->dev_sep_list, sep_list) {
|
|
|
|
|
- tmp_tpg = tmp_port->sep_tpg;
|
|
|
|
|
- if (!tmp_tpg)
|
|
|
|
|
- continue;
|
|
|
|
|
- tmp_tf_ops = tmp_tpg->se_tpg_tfo;
|
|
|
|
|
- if (!tmp_tf_ops)
|
|
|
|
|
- continue;
|
|
|
|
|
- if (!tmp_tf_ops->get_fabric_proto_ident ||
|
|
|
|
|
- !tmp_tf_ops->tpg_parse_pr_out_transport_id)
|
|
|
|
|
- continue;
|
|
|
|
|
|
|
+ list_for_each_entry(tmp_lun, &dev->dev_sep_list, lun_dev_link) {
|
|
|
|
|
+ tmp_tpg = tmp_lun->lun_tpg;
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
* Look for the matching proto_ident provided by
|
|
* Look for the matching proto_ident provided by
|
|
|
* the received TransportID
|
|
* the received TransportID
|
|
|
*/
|
|
*/
|
|
|
- tmp_proto_ident = tmp_tf_ops->get_fabric_proto_ident(tmp_tpg);
|
|
|
|
|
- if (tmp_proto_ident != proto_ident)
|
|
|
|
|
|
|
+ if (tmp_tpg->proto_id != proto_ident)
|
|
|
continue;
|
|
continue;
|
|
|
- dest_rtpi = tmp_port->sep_rtpi;
|
|
|
|
|
|
|
+ dest_rtpi = tmp_lun->lun_rtpi;
|
|
|
|
|
|
|
|
- i_str = tmp_tf_ops->tpg_parse_pr_out_transport_id(
|
|
|
|
|
- tmp_tpg, (const char *)ptr, &tid_len,
|
|
|
|
|
- &iport_ptr);
|
|
|
|
|
|
|
+ i_str = target_parse_pr_out_transport_id(tmp_tpg,
|
|
|
|
|
+ (const char *)ptr, &tid_len, &iport_ptr);
|
|
|
if (!i_str)
|
|
if (!i_str)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
@@ -1569,12 +1586,12 @@ core_scsi3_decode_spec_i_port(
|
|
|
* from the decoded fabric module specific TransportID
|
|
* from the decoded fabric module specific TransportID
|
|
|
* at *i_str.
|
|
* at *i_str.
|
|
|
*/
|
|
*/
|
|
|
- spin_lock_irq(&tmp_tpg->acl_node_lock);
|
|
|
|
|
|
|
+ mutex_lock(&tmp_tpg->acl_node_mutex);
|
|
|
dest_node_acl = __core_tpg_get_initiator_node_acl(
|
|
dest_node_acl = __core_tpg_get_initiator_node_acl(
|
|
|
tmp_tpg, i_str);
|
|
tmp_tpg, i_str);
|
|
|
if (dest_node_acl)
|
|
if (dest_node_acl)
|
|
|
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
|
|
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
|
|
|
- spin_unlock_irq(&tmp_tpg->acl_node_lock);
|
|
|
|
|
|
|
+ mutex_unlock(&tmp_tpg->acl_node_mutex);
|
|
|
|
|
|
|
|
if (!dest_node_acl) {
|
|
if (!dest_node_acl) {
|
|
|
core_scsi3_tpg_undepend_item(tmp_tpg);
|
|
core_scsi3_tpg_undepend_item(tmp_tpg);
|
|
@@ -1644,7 +1661,7 @@ core_scsi3_decode_spec_i_port(
|
|
|
if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
|
pr_err("core_scsi3_lunacl_depend_item()"
|
|
pr_err("core_scsi3_lunacl_depend_item()"
|
|
|
" failed\n");
|
|
" failed\n");
|
|
|
- atomic_dec_mb(&dest_se_deve->pr_ref_count);
|
|
|
|
|
|
|
+ kref_put(&dest_se_deve->pr_kref, target_pr_kref_release);
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
core_scsi3_tpg_undepend_item(dest_tpg);
|
|
|
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
@@ -1652,7 +1669,7 @@ core_scsi3_decode_spec_i_port(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
|
|
pr_debug("SPC-3 PR SPEC_I_PT: Located %s Node: %s"
|
|
|
- " dest_se_deve mapped_lun: %u\n",
|
|
|
|
|
|
|
+ " dest_se_deve mapped_lun: %llu\n",
|
|
|
dest_tpg->se_tpg_tfo->get_fabric_name(),
|
|
dest_tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
dest_node_acl->initiatorname, dest_se_deve->mapped_lun);
|
|
dest_node_acl->initiatorname, dest_se_deve->mapped_lun);
|
|
|
|
|
|
|
@@ -1708,9 +1725,13 @@ core_scsi3_decode_spec_i_port(
|
|
|
* and then call __core_scsi3_add_registration() in the
|
|
* and then call __core_scsi3_add_registration() in the
|
|
|
* 2nd loop which will never fail.
|
|
* 2nd loop which will never fail.
|
|
|
*/
|
|
*/
|
|
|
|
|
+ dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
|
|
|
|
|
+ atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
|
|
|
|
|
+
|
|
|
dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
|
|
dest_pr_reg = __core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
- dest_node_acl, dest_se_deve, iport_ptr,
|
|
|
|
|
- sa_res_key, all_tg_pt, aptpl);
|
|
|
|
|
|
|
+ dest_node_acl, dest_lun, dest_se_deve,
|
|
|
|
|
+ dest_se_deve->mapped_lun, iport_ptr,
|
|
|
|
|
+ sa_res_key, all_tg_pt, aptpl);
|
|
|
if (!dest_pr_reg) {
|
|
if (!dest_pr_reg) {
|
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
core_scsi3_nodeacl_undepend_item(dest_node_acl);
|
|
@@ -1748,7 +1769,6 @@ core_scsi3_decode_spec_i_port(
|
|
|
dest_node_acl = tidh->dest_node_acl;
|
|
dest_node_acl = tidh->dest_node_acl;
|
|
|
dest_se_deve = tidh->dest_se_deve;
|
|
dest_se_deve = tidh->dest_se_deve;
|
|
|
dest_pr_reg = tidh->dest_pr_reg;
|
|
dest_pr_reg = tidh->dest_pr_reg;
|
|
|
- dest_local_nexus = tidh->dest_local_nexus;
|
|
|
|
|
|
|
|
|
|
list_del(&tidh->dest_list);
|
|
list_del(&tidh->dest_list);
|
|
|
kfree(tidh);
|
|
kfree(tidh);
|
|
@@ -1761,10 +1781,11 @@ core_scsi3_decode_spec_i_port(
|
|
|
|
|
|
|
|
pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
|
|
pr_debug("SPC-3 PR [%s] SPEC_I_PT: Successfully"
|
|
|
" registered Transport ID for Node: %s%s Mapped LUN:"
|
|
" registered Transport ID for Node: %s%s Mapped LUN:"
|
|
|
- " %u\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
|
|
- dest_node_acl->initiatorname, i_buf, dest_se_deve->mapped_lun);
|
|
|
|
|
|
|
+ " %llu\n", dest_tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
|
|
+ dest_node_acl->initiatorname, i_buf, (dest_se_deve) ?
|
|
|
|
|
+ dest_se_deve->mapped_lun : 0);
|
|
|
|
|
|
|
|
- if (dest_local_nexus)
|
|
|
|
|
|
|
+ if (!dest_se_deve)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
@@ -1785,7 +1806,6 @@ out:
|
|
|
dest_node_acl = tidh->dest_node_acl;
|
|
dest_node_acl = tidh->dest_node_acl;
|
|
|
dest_se_deve = tidh->dest_se_deve;
|
|
dest_se_deve = tidh->dest_se_deve;
|
|
|
dest_pr_reg = tidh->dest_pr_reg;
|
|
dest_pr_reg = tidh->dest_pr_reg;
|
|
|
- dest_local_nexus = tidh->dest_local_nexus;
|
|
|
|
|
|
|
|
|
|
list_del(&tidh->dest_list);
|
|
list_del(&tidh->dest_list);
|
|
|
kfree(tidh);
|
|
kfree(tidh);
|
|
@@ -1803,7 +1823,7 @@ out:
|
|
|
|
|
|
|
|
kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
|
|
kmem_cache_free(t10_pr_reg_cache, dest_pr_reg);
|
|
|
|
|
|
|
|
- if (dest_local_nexus)
|
|
|
|
|
|
|
+ if (!dest_se_deve)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
|
@@ -1818,7 +1838,6 @@ static int core_scsi3_update_aptpl_buf(
|
|
|
unsigned char *buf,
|
|
unsigned char *buf,
|
|
|
u32 pr_aptpl_buf_len)
|
|
u32 pr_aptpl_buf_len)
|
|
|
{
|
|
{
|
|
|
- struct se_lun *lun;
|
|
|
|
|
struct se_portal_group *tpg;
|
|
struct se_portal_group *tpg;
|
|
|
struct t10_pr_registration *pr_reg;
|
|
struct t10_pr_registration *pr_reg;
|
|
|
unsigned char tmp[512], isid_buf[32];
|
|
unsigned char tmp[512], isid_buf[32];
|
|
@@ -1837,7 +1856,6 @@ static int core_scsi3_update_aptpl_buf(
|
|
|
tmp[0] = '\0';
|
|
tmp[0] = '\0';
|
|
|
isid_buf[0] = '\0';
|
|
isid_buf[0] = '\0';
|
|
|
tpg = pr_reg->pr_reg_nacl->se_tpg;
|
|
tpg = pr_reg->pr_reg_nacl->se_tpg;
|
|
|
- lun = pr_reg->pr_reg_tg_pt_lun;
|
|
|
|
|
/*
|
|
/*
|
|
|
* Write out any ISID value to APTPL metadata that was included
|
|
* Write out any ISID value to APTPL metadata that was included
|
|
|
* in the original registration.
|
|
* in the original registration.
|
|
@@ -1856,7 +1874,7 @@ static int core_scsi3_update_aptpl_buf(
|
|
|
"sa_res_key=%llu\n"
|
|
"sa_res_key=%llu\n"
|
|
|
"res_holder=1\nres_type=%02x\n"
|
|
"res_holder=1\nres_type=%02x\n"
|
|
|
"res_scope=%02x\nres_all_tg_pt=%d\n"
|
|
"res_scope=%02x\nres_all_tg_pt=%d\n"
|
|
|
- "mapped_lun=%u\n", reg_count,
|
|
|
|
|
|
|
+ "mapped_lun=%llu\n", reg_count,
|
|
|
tpg->se_tpg_tfo->get_fabric_name(),
|
|
tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
pr_reg->pr_reg_nacl->initiatorname, isid_buf,
|
|
pr_reg->pr_reg_nacl->initiatorname, isid_buf,
|
|
|
pr_reg->pr_res_key, pr_reg->pr_res_type,
|
|
pr_reg->pr_res_key, pr_reg->pr_res_type,
|
|
@@ -1866,7 +1884,7 @@ static int core_scsi3_update_aptpl_buf(
|
|
|
snprintf(tmp, 512, "PR_REG_START: %d\n"
|
|
snprintf(tmp, 512, "PR_REG_START: %d\n"
|
|
|
"initiator_fabric=%s\ninitiator_node=%s\n%s"
|
|
"initiator_fabric=%s\ninitiator_node=%s\n%s"
|
|
|
"sa_res_key=%llu\nres_holder=0\n"
|
|
"sa_res_key=%llu\nres_holder=0\n"
|
|
|
- "res_all_tg_pt=%d\nmapped_lun=%u\n",
|
|
|
|
|
|
|
+ "res_all_tg_pt=%d\nmapped_lun=%llu\n",
|
|
|
reg_count, tpg->se_tpg_tfo->get_fabric_name(),
|
|
reg_count, tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
pr_reg->pr_reg_nacl->initiatorname, isid_buf,
|
|
pr_reg->pr_reg_nacl->initiatorname, isid_buf,
|
|
|
pr_reg->pr_res_key, pr_reg->pr_reg_all_tg_pt,
|
|
pr_reg->pr_res_key, pr_reg->pr_reg_all_tg_pt,
|
|
@@ -1885,11 +1903,12 @@ static int core_scsi3_update_aptpl_buf(
|
|
|
* Include information about the associated SCSI target port.
|
|
* Include information about the associated SCSI target port.
|
|
|
*/
|
|
*/
|
|
|
snprintf(tmp, 512, "target_fabric=%s\ntarget_node=%s\n"
|
|
snprintf(tmp, 512, "target_fabric=%s\ntarget_node=%s\n"
|
|
|
- "tpgt=%hu\nport_rtpi=%hu\ntarget_lun=%u\nPR_REG_END:"
|
|
|
|
|
|
|
+ "tpgt=%hu\nport_rtpi=%hu\ntarget_lun=%llu\nPR_REG_END:"
|
|
|
" %d\n", tpg->se_tpg_tfo->get_fabric_name(),
|
|
" %d\n", tpg->se_tpg_tfo->get_fabric_name(),
|
|
|
tpg->se_tpg_tfo->tpg_get_wwn(tpg),
|
|
tpg->se_tpg_tfo->tpg_get_wwn(tpg),
|
|
|
tpg->se_tpg_tfo->tpg_get_tag(tpg),
|
|
tpg->se_tpg_tfo->tpg_get_tag(tpg),
|
|
|
- lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
|
|
|
|
|
|
|
+ pr_reg->tg_pt_sep_rtpi, pr_reg->pr_aptpl_target_lun,
|
|
|
|
|
+ reg_count);
|
|
|
|
|
|
|
|
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
|
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
|
|
pr_err("Unable to update renaming APTPL metadata,"
|
|
pr_err("Unable to update renaming APTPL metadata,"
|
|
@@ -2000,7 +2019,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
{
|
|
{
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
- struct se_dev_entry *se_deve;
|
|
|
|
|
struct se_lun *se_lun = cmd->se_lun;
|
|
struct se_lun *se_lun = cmd->se_lun;
|
|
|
struct se_portal_group *se_tpg;
|
|
struct se_portal_group *se_tpg;
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
|
|
@@ -2014,7 +2032,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
}
|
|
}
|
|
|
se_tpg = se_sess->se_tpg;
|
|
se_tpg = se_sess->se_tpg;
|
|
|
- se_deve = se_sess->se_node_acl->device_list[cmd->orig_fe_lun];
|
|
|
|
|
|
|
|
|
|
if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
|
|
if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
|
|
|
memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
|
|
memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
|
|
@@ -2045,7 +2062,8 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
* Logical Unit of the SCSI device server.
|
|
* Logical Unit of the SCSI device server.
|
|
|
*/
|
|
*/
|
|
|
if (core_scsi3_alloc_registration(cmd->se_dev,
|
|
if (core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
- se_sess->se_node_acl, se_deve, isid_ptr,
|
|
|
|
|
|
|
+ se_sess->se_node_acl, cmd->se_lun,
|
|
|
|
|
+ NULL, cmd->orig_fe_lun, isid_ptr,
|
|
|
sa_res_key, all_tg_pt, aptpl,
|
|
sa_res_key, all_tg_pt, aptpl,
|
|
|
register_type, 0)) {
|
|
register_type, 0)) {
|
|
|
pr_err("Unable to allocate"
|
|
pr_err("Unable to allocate"
|
|
@@ -2066,7 +2084,6 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
if (ret != 0)
|
|
if (ret != 0)
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
return core_scsi3_update_and_write_aptpl(dev, aptpl);
|
|
return core_scsi3_update_and_write_aptpl(dev, aptpl);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -2180,7 +2197,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key,
|
|
|
&pr_tmpl->registration_list,
|
|
&pr_tmpl->registration_list,
|
|
|
pr_reg_list) {
|
|
pr_reg_list) {
|
|
|
|
|
|
|
|
- core_scsi3_ua_allocate(
|
|
|
|
|
|
|
+ target_ua_allocate_lun(
|
|
|
pr_reg_p->pr_reg_nacl,
|
|
pr_reg_p->pr_reg_nacl,
|
|
|
pr_reg_p->pr_res_mapped_lun,
|
|
pr_reg_p->pr_res_mapped_lun,
|
|
|
0x2A,
|
|
0x2A,
|
|
@@ -2607,7 +2624,7 @@ core_scsi3_emulate_pro_release(struct se_cmd *cmd, int type, int scope,
|
|
|
if (pr_reg_p == pr_reg)
|
|
if (pr_reg_p == pr_reg)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- core_scsi3_ua_allocate(pr_reg_p->pr_reg_nacl,
|
|
|
|
|
|
|
+ target_ua_allocate_lun(pr_reg_p->pr_reg_nacl,
|
|
|
pr_reg_p->pr_res_mapped_lun,
|
|
pr_reg_p->pr_res_mapped_lun,
|
|
|
0x2A, ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
0x2A, ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
|
}
|
|
}
|
|
@@ -2630,7 +2647,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
|
|
|
- u32 pr_res_mapped_lun = 0;
|
|
|
|
|
|
|
+ u64 pr_res_mapped_lun = 0;
|
|
|
int calling_it_nexus = 0;
|
|
int calling_it_nexus = 0;
|
|
|
/*
|
|
/*
|
|
|
* Locate the existing *pr_reg via struct se_node_acl pointers
|
|
* Locate the existing *pr_reg via struct se_node_acl pointers
|
|
@@ -2692,7 +2709,7 @@ core_scsi3_emulate_pro_clear(struct se_cmd *cmd, u64 res_key)
|
|
|
* additional sense code set to RESERVATIONS PREEMPTED.
|
|
* additional sense code set to RESERVATIONS PREEMPTED.
|
|
|
*/
|
|
*/
|
|
|
if (!calling_it_nexus)
|
|
if (!calling_it_nexus)
|
|
|
- core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun,
|
|
|
|
|
|
|
+ target_ua_allocate_lun(pr_reg_nacl, pr_res_mapped_lun,
|
|
|
0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED);
|
|
0x2A, ASCQ_2AH_RESERVATIONS_PREEMPTED);
|
|
|
}
|
|
}
|
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
@@ -2786,7 +2803,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
|
|
|
LIST_HEAD(preempt_and_abort_list);
|
|
LIST_HEAD(preempt_and_abort_list);
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp, *pr_reg_n, *pr_res_holder;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
- u32 pr_res_mapped_lun = 0;
|
|
|
|
|
|
|
+ u64 pr_res_mapped_lun = 0;
|
|
|
int all_reg = 0, calling_it_nexus = 0;
|
|
int all_reg = 0, calling_it_nexus = 0;
|
|
|
bool sa_res_key_unmatched = sa_res_key != 0;
|
|
bool sa_res_key_unmatched = sa_res_key != 0;
|
|
|
int prh_type = 0, prh_scope = 0;
|
|
int prh_type = 0, prh_scope = 0;
|
|
@@ -2901,7 +2918,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
|
|
|
NULL, 0);
|
|
NULL, 0);
|
|
|
}
|
|
}
|
|
|
if (!calling_it_nexus)
|
|
if (!calling_it_nexus)
|
|
|
- core_scsi3_ua_allocate(pr_reg_nacl,
|
|
|
|
|
|
|
+ target_ua_allocate_lun(pr_reg_nacl,
|
|
|
pr_res_mapped_lun, 0x2A,
|
|
pr_res_mapped_lun, 0x2A,
|
|
|
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
|
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
|
|
}
|
|
}
|
|
@@ -3007,7 +3024,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
|
|
|
* persistent reservation and/or registration, with the
|
|
* persistent reservation and/or registration, with the
|
|
|
* additional sense code set to REGISTRATIONS PREEMPTED;
|
|
* additional sense code set to REGISTRATIONS PREEMPTED;
|
|
|
*/
|
|
*/
|
|
|
- core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
|
|
|
|
|
|
|
+ target_ua_allocate_lun(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
|
|
|
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
|
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
|
|
}
|
|
}
|
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
spin_unlock(&pr_tmpl->registration_lock);
|
|
@@ -3040,7 +3057,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
|
|
|
if (calling_it_nexus)
|
|
if (calling_it_nexus)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- core_scsi3_ua_allocate(pr_reg->pr_reg_nacl,
|
|
|
|
|
|
|
+ target_ua_allocate_lun(pr_reg->pr_reg_nacl,
|
|
|
pr_reg->pr_res_mapped_lun, 0x2A,
|
|
pr_reg->pr_res_mapped_lun, 0x2A,
|
|
|
ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
ASCQ_2AH_RESERVATIONS_RELEASED);
|
|
|
}
|
|
}
|
|
@@ -3099,15 +3116,14 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
|
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
struct se_session *se_sess = cmd->se_sess;
|
|
|
struct se_device *dev = cmd->se_dev;
|
|
struct se_device *dev = cmd->se_dev;
|
|
|
struct se_dev_entry *dest_se_deve = NULL;
|
|
struct se_dev_entry *dest_se_deve = NULL;
|
|
|
- struct se_lun *se_lun = cmd->se_lun;
|
|
|
|
|
|
|
+ struct se_lun *se_lun = cmd->se_lun, *tmp_lun;
|
|
|
struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
|
|
struct se_node_acl *pr_res_nacl, *pr_reg_nacl, *dest_node_acl = NULL;
|
|
|
- struct se_port *se_port;
|
|
|
|
|
struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
|
|
struct se_portal_group *se_tpg, *dest_se_tpg = NULL;
|
|
|
const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
|
|
const struct target_core_fabric_ops *dest_tf_ops = NULL, *tf_ops;
|
|
|
struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
|
|
struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
unsigned char *buf;
|
|
unsigned char *buf;
|
|
|
- unsigned char *initiator_str;
|
|
|
|
|
|
|
+ const unsigned char *initiator_str;
|
|
|
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
|
|
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
|
|
|
u32 tid_len, tmp_tid_len;
|
|
u32 tid_len, tmp_tid_len;
|
|
|
int new_reg = 0, type, scope, matching_iname;
|
|
int new_reg = 0, type, scope, matching_iname;
|
|
@@ -3186,12 +3202,10 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
spin_lock(&dev->se_port_lock);
|
|
spin_lock(&dev->se_port_lock);
|
|
|
- list_for_each_entry(se_port, &dev->dev_sep_list, sep_list) {
|
|
|
|
|
- if (se_port->sep_rtpi != rtpi)
|
|
|
|
|
- continue;
|
|
|
|
|
- dest_se_tpg = se_port->sep_tpg;
|
|
|
|
|
- if (!dest_se_tpg)
|
|
|
|
|
|
|
+ list_for_each_entry(tmp_lun, &dev->dev_sep_list, lun_dev_link) {
|
|
|
|
|
+ if (tmp_lun->lun_rtpi != rtpi)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
+ dest_se_tpg = tmp_lun->lun_tpg;
|
|
|
dest_tf_ops = dest_se_tpg->se_tpg_tfo;
|
|
dest_tf_ops = dest_se_tpg->se_tpg_tfo;
|
|
|
if (!dest_tf_ops)
|
|
if (!dest_tf_ops)
|
|
|
continue;
|
|
continue;
|
|
@@ -3230,23 +3244,16 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
|
|
|
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
|
|
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
|
|
|
" 0x%02x\n", proto_ident);
|
|
" 0x%02x\n", proto_ident);
|
|
|
|
|
|
|
|
- if (proto_ident != dest_tf_ops->get_fabric_proto_ident(dest_se_tpg)) {
|
|
|
|
|
|
|
+ if (proto_ident != dest_se_tpg->proto_id) {
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Received"
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Received"
|
|
|
" proto_ident: 0x%02x does not match ident: 0x%02x"
|
|
" proto_ident: 0x%02x does not match ident: 0x%02x"
|
|
|
" from fabric: %s\n", proto_ident,
|
|
" from fabric: %s\n", proto_ident,
|
|
|
- dest_tf_ops->get_fabric_proto_ident(dest_se_tpg),
|
|
|
|
|
|
|
+ dest_se_tpg->proto_id,
|
|
|
dest_tf_ops->get_fabric_name());
|
|
dest_tf_ops->get_fabric_name());
|
|
|
ret = TCM_INVALID_PARAMETER_LIST;
|
|
ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
- if (dest_tf_ops->tpg_parse_pr_out_transport_id == NULL) {
|
|
|
|
|
- pr_err("SPC-3 PR REGISTER_AND_MOVE: Fabric does not"
|
|
|
|
|
- " containg a valid tpg_parse_pr_out_transport_id"
|
|
|
|
|
- " function pointer\n");
|
|
|
|
|
- ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
|
|
- goto out;
|
|
|
|
|
- }
|
|
|
|
|
- initiator_str = dest_tf_ops->tpg_parse_pr_out_transport_id(dest_se_tpg,
|
|
|
|
|
|
|
+ initiator_str = target_parse_pr_out_transport_id(dest_se_tpg,
|
|
|
(const char *)&buf[24], &tmp_tid_len, &iport_ptr);
|
|
(const char *)&buf[24], &tmp_tid_len, &iport_ptr);
|
|
|
if (!initiator_str) {
|
|
if (!initiator_str) {
|
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
|
|
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
|
|
@@ -3295,12 +3302,12 @@ after_iport_check:
|
|
|
/*
|
|
/*
|
|
|
* Locate the destination struct se_node_acl from the received Transport ID
|
|
* Locate the destination struct se_node_acl from the received Transport ID
|
|
|
*/
|
|
*/
|
|
|
- spin_lock_irq(&dest_se_tpg->acl_node_lock);
|
|
|
|
|
|
|
+ mutex_lock(&dest_se_tpg->acl_node_mutex);
|
|
|
dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg,
|
|
dest_node_acl = __core_tpg_get_initiator_node_acl(dest_se_tpg,
|
|
|
initiator_str);
|
|
initiator_str);
|
|
|
if (dest_node_acl)
|
|
if (dest_node_acl)
|
|
|
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
|
|
atomic_inc_mb(&dest_node_acl->acl_pr_ref_count);
|
|
|
- spin_unlock_irq(&dest_se_tpg->acl_node_lock);
|
|
|
|
|
|
|
+ mutex_unlock(&dest_se_tpg->acl_node_mutex);
|
|
|
|
|
|
|
|
if (!dest_node_acl) {
|
|
if (!dest_node_acl) {
|
|
|
pr_err("Unable to locate %s dest_node_acl for"
|
|
pr_err("Unable to locate %s dest_node_acl for"
|
|
@@ -3337,14 +3344,14 @@ after_iport_check:
|
|
|
|
|
|
|
|
if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
if (core_scsi3_lunacl_depend_item(dest_se_deve)) {
|
|
|
pr_err("core_scsi3_lunacl_depend_item() failed\n");
|
|
pr_err("core_scsi3_lunacl_depend_item() failed\n");
|
|
|
- atomic_dec_mb(&dest_se_deve->pr_ref_count);
|
|
|
|
|
|
|
+ kref_put(&dest_se_deve->pr_kref, target_pr_kref_release);
|
|
|
dest_se_deve = NULL;
|
|
dest_se_deve = NULL;
|
|
|
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
|
|
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Located %s node %s LUN"
|
|
|
- " ACL for dest_se_deve->mapped_lun: %u\n",
|
|
|
|
|
|
|
+ " ACL for dest_se_deve->mapped_lun: %llu\n",
|
|
|
dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname,
|
|
dest_tf_ops->get_fabric_name(), dest_node_acl->initiatorname,
|
|
|
dest_se_deve->mapped_lun);
|
|
dest_se_deve->mapped_lun);
|
|
|
|
|
|
|
@@ -3421,13 +3428,17 @@ after_iport_check:
|
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
|
iport_ptr);
|
|
iport_ptr);
|
|
|
if (!dest_pr_reg) {
|
|
if (!dest_pr_reg) {
|
|
|
- if (core_scsi3_alloc_registration(cmd->se_dev,
|
|
|
|
|
- dest_node_acl, dest_se_deve, iport_ptr,
|
|
|
|
|
- sa_res_key, 0, aptpl, 2, 1)) {
|
|
|
|
|
- spin_unlock(&dev->dev_reservation_lock);
|
|
|
|
|
|
|
+ struct se_lun *dest_lun = rcu_dereference_check(dest_se_deve->se_lun,
|
|
|
|
|
+ atomic_read(&dest_se_deve->pr_kref.refcount) != 0);
|
|
|
|
|
+
|
|
|
|
|
+ spin_unlock(&dev->dev_reservation_lock);
|
|
|
|
|
+ if (core_scsi3_alloc_registration(cmd->se_dev, dest_node_acl,
|
|
|
|
|
+ dest_lun, dest_se_deve, dest_se_deve->mapped_lun,
|
|
|
|
|
+ iport_ptr, sa_res_key, 0, aptpl, 2, 1)) {
|
|
|
ret = TCM_INVALID_PARAMETER_LIST;
|
|
ret = TCM_INVALID_PARAMETER_LIST;
|
|
|
goto out;
|
|
goto out;
|
|
|
}
|
|
}
|
|
|
|
|
+ spin_lock(&dev->dev_reservation_lock);
|
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
dest_pr_reg = __core_scsi3_locate_pr_reg(dev, dest_node_acl,
|
|
|
iport_ptr);
|
|
iport_ptr);
|
|
|
new_reg = 1;
|
|
new_reg = 1;
|
|
@@ -3883,9 +3894,10 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp;
|
|
struct t10_pr_registration *pr_reg, *pr_reg_tmp;
|
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
|
|
unsigned char *buf;
|
|
unsigned char *buf;
|
|
|
- u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
|
|
|
|
|
|
|
+ u32 add_desc_len = 0, add_len = 0;
|
|
|
u32 off = 8; /* off into first Full Status descriptor */
|
|
u32 off = 8; /* off into first Full Status descriptor */
|
|
|
int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
|
|
int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
|
|
|
|
|
+ int exp_desc_len, desc_len;
|
|
|
bool all_reg = false;
|
|
bool all_reg = false;
|
|
|
|
|
|
|
|
if (cmd->data_length < 8) {
|
|
if (cmd->data_length < 8) {
|
|
@@ -3930,10 +3942,10 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
* Determine expected length of $FABRIC_MOD specific
|
|
* Determine expected length of $FABRIC_MOD specific
|
|
|
* TransportID full status descriptor..
|
|
* TransportID full status descriptor..
|
|
|
*/
|
|
*/
|
|
|
- exp_desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id_len(
|
|
|
|
|
- se_tpg, se_nacl, pr_reg, &format_code);
|
|
|
|
|
-
|
|
|
|
|
- if ((exp_desc_len + add_len) > cmd->data_length) {
|
|
|
|
|
|
|
+ exp_desc_len = target_get_pr_transport_id_len(se_nacl, pr_reg,
|
|
|
|
|
+ &format_code);
|
|
|
|
|
+ if (exp_desc_len < 0 ||
|
|
|
|
|
+ exp_desc_len + add_len > cmd->data_length) {
|
|
|
pr_warn("SPC-3 PRIN READ_FULL_STATUS ran"
|
|
pr_warn("SPC-3 PRIN READ_FULL_STATUS ran"
|
|
|
" out of buffer: %d\n", cmd->data_length);
|
|
" out of buffer: %d\n", cmd->data_length);
|
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
@@ -3990,21 +4002,26 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
|
|
* IDENTIFIER field are not defined by this standard.
|
|
* IDENTIFIER field are not defined by this standard.
|
|
|
*/
|
|
*/
|
|
|
if (!pr_reg->pr_reg_all_tg_pt) {
|
|
if (!pr_reg->pr_reg_all_tg_pt) {
|
|
|
- struct se_port *port = pr_reg->pr_reg_tg_pt_lun->lun_sep;
|
|
|
|
|
|
|
+ u16 sep_rtpi = pr_reg->tg_pt_sep_rtpi;
|
|
|
|
|
|
|
|
- buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
|
|
|
|
|
- buf[off++] = (port->sep_rtpi & 0xff);
|
|
|
|
|
|
|
+ buf[off++] = ((sep_rtpi >> 8) & 0xff);
|
|
|
|
|
+ buf[off++] = (sep_rtpi & 0xff);
|
|
|
} else
|
|
} else
|
|
|
off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */
|
|
off += 2; /* Skip over RELATIVE TARGET PORT IDENTIFIER */
|
|
|
|
|
|
|
|
|
|
+ buf[off+4] = se_tpg->proto_id;
|
|
|
|
|
+
|
|
|
/*
|
|
/*
|
|
|
- * Now, have the $FABRIC_MOD fill in the protocol identifier
|
|
|
|
|
|
|
+ * Now, have the $FABRIC_MOD fill in the transport ID.
|
|
|
*/
|
|
*/
|
|
|
- desc_len = se_tpg->se_tpg_tfo->tpg_get_pr_transport_id(se_tpg,
|
|
|
|
|
- se_nacl, pr_reg, &format_code, &buf[off+4]);
|
|
|
|
|
|
|
+ desc_len = target_get_pr_transport_id(se_nacl, pr_reg,
|
|
|
|
|
+ &format_code, &buf[off+4]);
|
|
|
|
|
|
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
spin_lock(&pr_tmpl->registration_lock);
|
|
|
atomic_dec_mb(&pr_reg->pr_res_holders);
|
|
atomic_dec_mb(&pr_reg->pr_res_holders);
|
|
|
|
|
+
|
|
|
|
|
+ if (desc_len < 0)
|
|
|
|
|
+ break;
|
|
|
/*
|
|
/*
|
|
|
* Set the ADDITIONAL DESCRIPTOR LENGTH
|
|
* Set the ADDITIONAL DESCRIPTOR LENGTH
|
|
|
*/
|
|
*/
|