forked from Minki/linux
target: simplify reservations code
We do not support host-level reservations for the pscsi backend, and all virtual backends are newere than SCSI-2, so just make the combined SPC-3 + SCSI-2 support the only supported variant and kill the switches for the different implementations, given that this code handles the no-op version just fine. (hch: Update DRF_SPC2_RESERVATIONS lock usage) Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
019c4ca621
commit
d977f4377f
@ -970,13 +970,8 @@ static struct target_core_dev_pr_attribute target_core_dev_pr_##_name = \
|
||||
__CONFIGFS_EATTR_RO(_name, \
|
||||
target_core_dev_pr_show_attr_##_name);
|
||||
|
||||
/*
|
||||
* res_holder
|
||||
*/
|
||||
static ssize_t target_core_dev_pr_show_spc3_res(
|
||||
struct se_device *dev,
|
||||
char *page,
|
||||
ssize_t *len)
|
||||
static ssize_t target_core_dev_pr_show_spc3_res(struct se_device *dev,
|
||||
char *page)
|
||||
{
|
||||
struct se_node_acl *se_nacl;
|
||||
struct t10_pr_registration *pr_reg;
|
||||
@ -985,68 +980,52 @@ static ssize_t target_core_dev_pr_show_spc3_res(
|
||||
|
||||
memset(i_buf, 0, PR_REG_ISID_ID_LEN);
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
pr_reg = dev->dev_pr_res_holder;
|
||||
if (!pr_reg) {
|
||||
*len += sprintf(page + *len, "No SPC-3 Reservation holder\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return *len;
|
||||
}
|
||||
if (!pr_reg)
|
||||
return sprintf(page, "No SPC-3 Reservation holder\n");
|
||||
|
||||
se_nacl = pr_reg->pr_reg_nacl;
|
||||
prf_isid = core_pr_dump_initiator_port(pr_reg, &i_buf[0],
|
||||
PR_REG_ISID_ID_LEN);
|
||||
|
||||
*len += sprintf(page + *len, "SPC-3 Reservation: %s Initiator: %s%s\n",
|
||||
return sprintf(page, "SPC-3 Reservation: %s Initiator: %s%s\n",
|
||||
se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
|
||||
se_nacl->initiatorname, (prf_isid) ? &i_buf[0] : "");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
return *len;
|
||||
}
|
||||
|
||||
static ssize_t target_core_dev_pr_show_spc2_res(
|
||||
struct se_device *dev,
|
||||
char *page,
|
||||
ssize_t *len)
|
||||
static ssize_t target_core_dev_pr_show_spc2_res(struct se_device *dev,
|
||||
char *page)
|
||||
{
|
||||
struct se_node_acl *se_nacl;
|
||||
ssize_t len;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
se_nacl = dev->dev_reserved_node_acl;
|
||||
if (!se_nacl) {
|
||||
*len += sprintf(page + *len, "No SPC-2 Reservation holder\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return *len;
|
||||
if (se_nacl) {
|
||||
len = sprintf(page,
|
||||
"SPC-2 Reservation: %s Initiator: %s\n",
|
||||
se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
|
||||
se_nacl->initiatorname);
|
||||
} else {
|
||||
len = sprintf(page, "No SPC-2 Reservation holder\n");
|
||||
}
|
||||
*len += sprintf(page + *len, "SPC-2 Reservation: %s Initiator: %s\n",
|
||||
se_nacl->se_tpg->se_tpg_tfo->get_fabric_name(),
|
||||
se_nacl->initiatorname);
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
return *len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t target_core_dev_pr_show_attr_res_holder(struct se_device *dev,
|
||||
char *page)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int ret;
|
||||
|
||||
switch (dev->t10_pr.res_type) {
|
||||
case SPC3_PERSISTENT_RESERVATIONS:
|
||||
target_core_dev_pr_show_spc3_res(dev, page, &len);
|
||||
break;
|
||||
case SPC2_RESERVATIONS:
|
||||
target_core_dev_pr_show_spc2_res(dev, page, &len);
|
||||
break;
|
||||
case SPC_PASSTHROUGH:
|
||||
len += sprintf(page+len, "Passthrough\n");
|
||||
break;
|
||||
default:
|
||||
len += sprintf(page+len, "Unknown\n");
|
||||
break;
|
||||
}
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return sprintf(page, "Passthrough\n");
|
||||
|
||||
return len;
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
ret = target_core_dev_pr_show_spc2_res(dev, page);
|
||||
else
|
||||
ret = target_core_dev_pr_show_spc3_res(dev, page);
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SE_DEV_PR_ATTR_RO(res_holder);
|
||||
@ -1054,31 +1033,20 @@ SE_DEV_PR_ATTR_RO(res_holder);
|
||||
static ssize_t target_core_dev_pr_show_attr_res_pr_all_tgt_pts(
|
||||
struct se_device *dev, char *page)
|
||||
{
|
||||
struct t10_pr_registration *pr_reg;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
return len;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
pr_reg = dev->dev_pr_res_holder;
|
||||
if (!pr_reg) {
|
||||
if (!dev->dev_pr_res_holder) {
|
||||
len = sprintf(page, "No SPC-3 Reservation holder\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
}
|
||||
/*
|
||||
* 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)
|
||||
} else if (dev->dev_pr_res_holder->pr_reg_all_tg_pt) {
|
||||
len = sprintf(page, "SPC-3 Reservation: All Target"
|
||||
" Ports registration\n");
|
||||
else
|
||||
} else {
|
||||
len = sprintf(page, "SPC-3 Reservation: Single"
|
||||
" Target Port registration\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
}
|
||||
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -1087,9 +1055,6 @@ SE_DEV_PR_ATTR_RO(res_pr_all_tgt_pts);
|
||||
static ssize_t target_core_dev_pr_show_attr_res_pr_generation(
|
||||
struct se_device *dev, char *page)
|
||||
{
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
return 0;
|
||||
|
||||
return sprintf(page, "0x%08x\n", dev->t10_pr.pr_generation);
|
||||
}
|
||||
|
||||
@ -1108,16 +1073,13 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
|
||||
struct target_core_fabric_ops *tfo;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
return len;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
pr_reg = dev->dev_pr_res_holder;
|
||||
if (!pr_reg) {
|
||||
len = sprintf(page, "No SPC-3 Reservation holder\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
se_nacl = pr_reg->pr_reg_nacl;
|
||||
se_tpg = se_nacl->se_tpg;
|
||||
lun = pr_reg->pr_reg_tg_pt_lun;
|
||||
@ -1131,8 +1093,9 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_holder_tg_port(
|
||||
" %s Logical Unit: %u\n", lun->lun_sep->sep_rtpi,
|
||||
tfo->get_fabric_name(), tfo->tpg_get_tag(se_tpg),
|
||||
tfo->get_fabric_name(), lun->unpacked_lun);
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
out_unlock:
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -1148,9 +1111,6 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
|
||||
ssize_t len = 0;
|
||||
int reg_count = 0, prf_isid;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
return len;
|
||||
|
||||
len += sprintf(page+len, "SPC-3 PR Registrations:\n");
|
||||
|
||||
spin_lock(&dev->t10_pr.registration_lock);
|
||||
@ -1190,20 +1150,16 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_type(
|
||||
struct t10_pr_registration *pr_reg;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
return len;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
pr_reg = dev->dev_pr_res_holder;
|
||||
if (!pr_reg) {
|
||||
if (pr_reg) {
|
||||
len = sprintf(page, "SPC-3 Reservation Type: %s\n",
|
||||
core_scsi3_pr_dump_type(pr_reg->pr_res_type));
|
||||
} else {
|
||||
len = sprintf(page, "No SPC-3 Reservation holder\n");
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
}
|
||||
len = sprintf(page, "SPC-3 Reservation Type: %s\n",
|
||||
core_scsi3_pr_dump_type(pr_reg->pr_res_type));
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -1212,24 +1168,12 @@ SE_DEV_PR_ATTR_RO(res_pr_type);
|
||||
static ssize_t target_core_dev_pr_show_attr_res_type(
|
||||
struct se_device *dev, char *page)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
|
||||
switch (dev->t10_pr.res_type) {
|
||||
case SPC3_PERSISTENT_RESERVATIONS:
|
||||
len = sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
|
||||
break;
|
||||
case SPC2_RESERVATIONS:
|
||||
len = sprintf(page, "SPC2_RESERVATIONS\n");
|
||||
break;
|
||||
case SPC_PASSTHROUGH:
|
||||
len = sprintf(page, "SPC_PASSTHROUGH\n");
|
||||
break;
|
||||
default:
|
||||
len = sprintf(page, "UNKNOWN\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return len;
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return sprintf(page, "SPC_PASSTHROUGH\n");
|
||||
else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return sprintf(page, "SPC2_RESERVATIONS\n");
|
||||
else
|
||||
return sprintf(page, "SPC3_PERSISTENT_RESERVATIONS\n");
|
||||
}
|
||||
|
||||
SE_DEV_PR_ATTR_RO(res_type);
|
||||
@ -1237,7 +1181,7 @@ SE_DEV_PR_ATTR_RO(res_type);
|
||||
static ssize_t target_core_dev_pr_show_attr_res_aptpl_active(
|
||||
struct se_device *dev, char *page)
|
||||
{
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return 0;
|
||||
|
||||
return sprintf(page, "APTPL Bit Status: %s\n",
|
||||
@ -1252,7 +1196,7 @@ SE_DEV_PR_ATTR_RO(res_aptpl_active);
|
||||
static ssize_t target_core_dev_pr_show_attr_res_aptpl_metadata(
|
||||
struct se_device *dev, char *page)
|
||||
{
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return 0;
|
||||
|
||||
return sprintf(page, "Ready to process PR APTPL metadata..\n");
|
||||
@ -1299,7 +1243,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
||||
u16 port_rpti = 0, tpgt = 0;
|
||||
u8 type = 0, scope;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return 0;
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return 0;
|
||||
|
||||
if (dev->export_count) {
|
||||
|
@ -1398,7 +1398,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
dev->dev_attrib.emulate_tas = DA_EMULATE_TAS;
|
||||
dev->dev_attrib.emulate_tpu = DA_EMULATE_TPU;
|
||||
dev->dev_attrib.emulate_tpws = DA_EMULATE_TPWS;
|
||||
dev->dev_attrib.emulate_reservations = DA_EMULATE_RESERVATIONS;
|
||||
dev->dev_attrib.emulate_alua = DA_EMULATE_ALUA;
|
||||
dev->dev_attrib.enforce_pr_isids = DA_ENFORCE_PR_ISIDS;
|
||||
dev->dev_attrib.is_nonrot = DA_IS_NONROT;
|
||||
@ -1447,8 +1446,6 @@ int target_configure_device(struct se_device *dev)
|
||||
dev->dev_index = scsi_get_new_index(SCSI_DEVICE_INDEX);
|
||||
dev->creation_time = get_jiffies_64();
|
||||
|
||||
core_setup_reservations(dev);
|
||||
|
||||
ret = core_setup_alua(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
@ -68,49 +68,32 @@ int core_pr_dump_initiator_port(
|
||||
static void __core_scsi3_complete_pro_release(struct se_device *, struct se_node_acl *,
|
||||
struct t10_pr_registration *, int);
|
||||
|
||||
static int core_scsi2_reservation_seq_non_holder(
|
||||
struct se_cmd *cmd,
|
||||
unsigned char *cdb,
|
||||
u32 pr_reg_type)
|
||||
static int target_scsi2_reservation_check(struct se_cmd *cmd)
|
||||
{
|
||||
switch (cdb[0]) {
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_session *sess = cmd->se_sess;
|
||||
|
||||
switch (cmd->t_task_cdb[0]) {
|
||||
case INQUIRY:
|
||||
case RELEASE:
|
||||
case RELEASE_10:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int core_scsi2_reservation_check(struct se_cmd *cmd, u32 *pr_reg_type)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_session *sess = cmd->se_sess;
|
||||
int ret;
|
||||
|
||||
if (!sess)
|
||||
if (!dev->dev_reserved_node_acl || !sess)
|
||||
return 0;
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
if (!dev->dev_reserved_node_acl || !sess) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return 0;
|
||||
}
|
||||
if (dev->dev_reserved_node_acl != sess->se_node_acl) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!(dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID)) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return 0;
|
||||
}
|
||||
ret = (dev->dev_res_bin_isid == sess->sess_bin_isid) ? 0 : -EINVAL;
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
if (dev->dev_reserved_node_acl != sess->se_node_acl)
|
||||
return -EBUSY;
|
||||
|
||||
return ret;
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS_WITH_ISID) {
|
||||
if (dev->dev_res_bin_isid != sess->sess_bin_isid)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct t10_pr_registration *core_scsi3_locate_pr_reg(struct se_device *,
|
||||
@ -123,12 +106,8 @@ static int target_check_scsi2_reservation_conflict(struct se_cmd *cmd)
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct t10_pr_registration *pr_reg;
|
||||
struct t10_reservation *pr_tmpl = &dev->t10_pr;
|
||||
int crh = (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS);
|
||||
int conflict = 0;
|
||||
|
||||
if (!crh)
|
||||
return -EINVAL;
|
||||
|
||||
pr_reg = core_scsi3_locate_pr_reg(cmd->se_dev, se_sess->se_node_acl,
|
||||
se_sess);
|
||||
if (pr_reg) {
|
||||
@ -319,9 +298,9 @@ out:
|
||||
*/
|
||||
static int core_scsi3_pr_seq_non_holder(
|
||||
struct se_cmd *cmd,
|
||||
unsigned char *cdb,
|
||||
u32 pr_reg_type)
|
||||
{
|
||||
unsigned char *cdb = cmd->t_task_cdb;
|
||||
struct se_dev_entry *se_deve;
|
||||
struct se_session *se_sess = cmd->se_sess;
|
||||
int other_cdb = 0, ignore_reg;
|
||||
@ -330,17 +309,11 @@ static int core_scsi3_pr_seq_non_holder(
|
||||
int we = 0; /* Write Exclusive */
|
||||
int legacy = 0; /* Act like a legacy device and return
|
||||
* RESERVATION CONFLICT on some CDBs */
|
||||
/*
|
||||
* A legacy SPC-2 reservation is being held.
|
||||
*/
|
||||
if (cmd->se_dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return core_scsi2_reservation_seq_non_holder(cmd,
|
||||
cdb, pr_reg_type);
|
||||
|
||||
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 core_scsi3_pr_reservation_check().
|
||||
* non-matching ISIDs in target_scsi3_pr_reservation_check().
|
||||
*/
|
||||
ignore_reg = (pr_reg_type & 0x80000000);
|
||||
if (ignore_reg)
|
||||
@ -563,6 +536,36 @@ static int core_scsi3_pr_seq_non_holder(
|
||||
return 1; /* Conflict by default */
|
||||
}
|
||||
|
||||
static int target_scsi3_pr_reservation_check(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_session *sess = cmd->se_sess;
|
||||
u32 pr_reg_type;
|
||||
|
||||
if (!dev->dev_pr_res_holder)
|
||||
return 0;
|
||||
|
||||
pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
|
||||
cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
|
||||
if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl)
|
||||
goto check_nonholder;
|
||||
|
||||
if (dev->dev_pr_res_holder->isid_present_at_reg) {
|
||||
if (dev->dev_pr_res_holder->pr_reg_bin_isid !=
|
||||
sess->sess_bin_isid) {
|
||||
pr_reg_type |= 0x80000000;
|
||||
goto check_nonholder;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
check_nonholder:
|
||||
if (core_scsi3_pr_seq_non_holder(cmd, pr_reg_type))
|
||||
return -EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 core_scsi3_pr_generation(struct se_device *dev)
|
||||
{
|
||||
u32 prg;
|
||||
@ -583,50 +586,6 @@ static u32 core_scsi3_pr_generation(struct se_device *dev)
|
||||
return prg;
|
||||
}
|
||||
|
||||
static int core_scsi3_pr_reservation_check(
|
||||
struct se_cmd *cmd,
|
||||
u32 *pr_reg_type)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_session *sess = cmd->se_sess;
|
||||
int ret;
|
||||
|
||||
if (!sess)
|
||||
return 0;
|
||||
/*
|
||||
* A legacy SPC-2 reservation is being held.
|
||||
*/
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return core_scsi2_reservation_check(cmd, pr_reg_type);
|
||||
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
if (!dev->dev_pr_res_holder) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return 0;
|
||||
}
|
||||
*pr_reg_type = dev->dev_pr_res_holder->pr_res_type;
|
||||
cmd->pr_res_key = dev->dev_pr_res_holder->pr_res_key;
|
||||
if (dev->dev_pr_res_holder->pr_reg_nacl != sess->se_node_acl) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!dev->dev_pr_res_holder->isid_present_at_reg) {
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
return 0;
|
||||
}
|
||||
ret = (dev->dev_pr_res_holder->pr_reg_bin_isid ==
|
||||
sess->sess_bin_isid) ? 0 : -EINVAL;
|
||||
/*
|
||||
* Use bit in *pr_reg_type to notify ISID mismatch in
|
||||
* core_scsi3_pr_seq_non_holder().
|
||||
*/
|
||||
if (ret != 0)
|
||||
*pr_reg_type |= 0x80000000;
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct t10_pr_registration *__core_scsi3_do_alloc_registration(
|
||||
struct se_device *dev,
|
||||
struct se_node_acl *nacl,
|
||||
@ -998,7 +957,7 @@ int core_scsi3_check_aptpl_registration(
|
||||
struct se_node_acl *nacl = lun_acl->se_lun_nacl;
|
||||
struct se_dev_entry *deve = nacl->device_list[lun_acl->mapped_lun];
|
||||
|
||||
if (dev->t10_pr.res_type != SPC3_PERSISTENT_RESERVATIONS)
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return 0;
|
||||
|
||||
return __core_scsi3_check_aptpl_registration(dev, tpg, lun,
|
||||
@ -4343,49 +4302,24 @@ int target_scsi3_emulate_pr_in(struct se_cmd *cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int core_pt_reservation_check(struct se_cmd *cmd, u32 *pr_res_type)
|
||||
int target_check_reservation(struct se_cmd *cmd)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
int ret;
|
||||
|
||||
static int core_pt_seq_non_holder(
|
||||
struct se_cmd *cmd,
|
||||
unsigned char *cdb,
|
||||
u32 pr_reg_type)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!cmd->se_sess)
|
||||
return 0;
|
||||
if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
|
||||
return 0;
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV)
|
||||
return 0;
|
||||
|
||||
void core_setup_reservations(struct se_device *dev)
|
||||
{
|
||||
struct t10_reservation *rest = &dev->t10_pr;
|
||||
spin_lock(&dev->dev_reservation_lock);
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
ret = target_scsi2_reservation_check(cmd);
|
||||
else
|
||||
ret = target_scsi3_pr_reservation_check(cmd);
|
||||
spin_unlock(&dev->dev_reservation_lock);
|
||||
|
||||
/*
|
||||
* If this device is from Target_Core_Mod/pSCSI, use the reservations
|
||||
* of the Underlying SCSI hardware. In Linux/SCSI terms, this can
|
||||
* cause a problem because libata and some SATA RAID HBAs appear
|
||||
* under Linux/SCSI, but to emulate reservations themselves.
|
||||
*/
|
||||
if ((dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE) ||
|
||||
(dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV &&
|
||||
!dev->dev_attrib.emulate_reservations)) {
|
||||
rest->res_type = SPC_PASSTHROUGH;
|
||||
rest->pr_ops.t10_reservation_check = &core_pt_reservation_check;
|
||||
rest->pr_ops.t10_seq_non_holder = &core_pt_seq_non_holder;
|
||||
pr_debug("%s: Using SPC_PASSTHROUGH, no reservation"
|
||||
" emulation\n", dev->transport->name);
|
||||
} else if (dev->transport->get_device_rev(dev) >= SCSI_3) {
|
||||
rest->res_type = SPC3_PERSISTENT_RESERVATIONS;
|
||||
rest->pr_ops.t10_reservation_check = &core_scsi3_pr_reservation_check;
|
||||
rest->pr_ops.t10_seq_non_holder = &core_scsi3_pr_seq_non_holder;
|
||||
pr_debug("%s: Using SPC3_PERSISTENT_RESERVATIONS"
|
||||
" emulation\n", dev->transport->name);
|
||||
} else {
|
||||
rest->res_type = SPC2_RESERVATIONS;
|
||||
rest->pr_ops.t10_reservation_check = &core_scsi2_reservation_check;
|
||||
rest->pr_ops.t10_seq_non_holder =
|
||||
&core_scsi2_reservation_seq_non_holder;
|
||||
pr_debug("%s: Using SPC2_RESERVATIONS emulation\n",
|
||||
dev->transport->name);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -63,6 +63,6 @@ extern unsigned char *core_scsi3_pr_dump_type(int);
|
||||
|
||||
extern int target_scsi3_emulate_pr_in(struct se_cmd *);
|
||||
extern int target_scsi3_emulate_pr_out(struct se_cmd *);
|
||||
extern void core_setup_reservations(struct se_device *);
|
||||
extern int target_check_reservation(struct se_cmd *cmd);
|
||||
|
||||
#endif /* TARGET_CORE_PR_H */
|
||||
|
@ -1003,14 +1003,12 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
||||
*size = (cdb[7] << 8) + cdb[8];
|
||||
break;
|
||||
case PERSISTENT_RESERVE_IN:
|
||||
if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
|
||||
cmd->execute_cmd = target_scsi3_emulate_pr_in;
|
||||
*size = (cdb[7] << 8) + cdb[8];
|
||||
cmd->execute_cmd = target_scsi3_emulate_pr_in;
|
||||
break;
|
||||
case PERSISTENT_RESERVE_OUT:
|
||||
if (dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
|
||||
cmd->execute_cmd = target_scsi3_emulate_pr_out;
|
||||
*size = (cdb[7] << 8) + cdb[8];
|
||||
cmd->execute_cmd = target_scsi3_emulate_pr_out;
|
||||
break;
|
||||
case RELEASE:
|
||||
case RELEASE_10:
|
||||
@ -1019,8 +1017,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
||||
else
|
||||
*size = cmd->data_length;
|
||||
|
||||
if (dev->t10_pr.res_type != SPC_PASSTHROUGH)
|
||||
cmd->execute_cmd = target_scsi2_reservation_release;
|
||||
cmd->execute_cmd = target_scsi2_reservation_release;
|
||||
break;
|
||||
case RESERVE:
|
||||
case RESERVE_10:
|
||||
@ -1033,15 +1030,7 @@ int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
||||
else
|
||||
*size = cmd->data_length;
|
||||
|
||||
/*
|
||||
* Setup the legacy emulated handler for SPC-2 and
|
||||
* >= SPC-3 compatible reservation handling (CRH=1)
|
||||
* Otherwise, we assume the underlying SCSI logic is
|
||||
* is running in SPC_PASSTHROUGH, and wants reservations
|
||||
* emulation disabled.
|
||||
*/
|
||||
if (dev->t10_pr.res_type != SPC_PASSTHROUGH)
|
||||
cmd->execute_cmd = target_scsi2_reservation_reserve;
|
||||
cmd->execute_cmd = target_scsi2_reservation_reserve;
|
||||
break;
|
||||
case REQUEST_SENSE:
|
||||
*size = cdb[4];
|
||||
|
@ -1103,7 +1103,6 @@ int target_setup_cmd_from_cdb(
|
||||
unsigned char *cdb)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
u32 pr_reg_type = 0;
|
||||
u8 alua_ascq = 0;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
@ -1180,20 +1179,13 @@ int target_setup_cmd_from_cdb(
|
||||
/*
|
||||
* Check status for SPC-3 Persistent Reservations
|
||||
*/
|
||||
if (dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) {
|
||||
if (dev->t10_pr.pr_ops.t10_seq_non_holder(
|
||||
cmd, cdb, pr_reg_type) != 0) {
|
||||
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
|
||||
cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
|
||||
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
||||
return -EBUSY;
|
||||
}
|
||||
/*
|
||||
* This means the CDB is allowed for the SCSI Initiator port
|
||||
* when said port is *NOT* holding the legacy SPC-2 or
|
||||
* SPC-3 Persistent Reservation.
|
||||
*/
|
||||
ret = target_check_reservation(cmd);
|
||||
if (ret) {
|
||||
cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
|
||||
cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
|
||||
cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = dev->transport->parse_cdb(cmd);
|
||||
|
@ -93,8 +93,6 @@
|
||||
*/
|
||||
#define DA_EMULATE_TPWS 0
|
||||
/* No Emulation for PSCSI by default */
|
||||
#define DA_EMULATE_RESERVATIONS 0
|
||||
/* No Emulation for PSCSI by default */
|
||||
#define DA_EMULATE_ALUA 0
|
||||
/* Enforce SCSI Initiator Port TransportID with 'ISID' for PR */
|
||||
#define DA_ENFORCE_PR_ISIDS 1
|
||||
@ -333,18 +331,6 @@ struct t10_wwn {
|
||||
struct list_head t10_vpd_list;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Used by TCM Core internally to signal if >= SPC-3 persistent reservations
|
||||
* emulation is enabled or disabled, or running in with TCM/pSCSI passthrough
|
||||
* mode
|
||||
*/
|
||||
typedef enum {
|
||||
SPC_PASSTHROUGH,
|
||||
SPC2_RESERVATIONS,
|
||||
SPC3_PERSISTENT_RESERVATIONS
|
||||
} t10_reservations_index_t;
|
||||
|
||||
struct t10_pr_registration {
|
||||
/* Used for fabrics that contain WWN+ISID */
|
||||
#define PR_REG_ISID_LEN 16
|
||||
@ -386,18 +372,6 @@ struct t10_pr_registration {
|
||||
struct list_head pr_reg_atp_mem_list;
|
||||
};
|
||||
|
||||
/*
|
||||
* This set of function pointer ops is set based upon SPC3_PERSISTENT_RESERVATIONS,
|
||||
* SPC2_RESERVATIONS or SPC_PASSTHROUGH in drivers/target/target_core_pr.c:
|
||||
* core_setup_reservations()
|
||||
*/
|
||||
struct t10_reservation_ops {
|
||||
int (*t10_reservation_check)(struct se_cmd *, u32 *);
|
||||
int (*t10_seq_non_holder)(struct se_cmd *, unsigned char *, u32);
|
||||
int (*t10_pr_register)(struct se_cmd *);
|
||||
int (*t10_pr_clear)(struct se_cmd *);
|
||||
};
|
||||
|
||||
struct t10_reservation {
|
||||
/* Reservation effects all target ports */
|
||||
int pr_all_tg_pt;
|
||||
@ -408,7 +382,6 @@ struct t10_reservation {
|
||||
#define PR_APTPL_BUF_LEN 8192
|
||||
u32 pr_aptpl_buf_len;
|
||||
u32 pr_generation;
|
||||
t10_reservations_index_t res_type;
|
||||
spinlock_t registration_lock;
|
||||
spinlock_t aptpl_reg_lock;
|
||||
/*
|
||||
@ -424,7 +397,6 @@ struct t10_reservation {
|
||||
struct se_node_acl *pr_res_holder;
|
||||
struct list_head registration_list;
|
||||
struct list_head aptpl_reg_list;
|
||||
struct t10_reservation_ops pr_ops;
|
||||
};
|
||||
|
||||
struct se_tmr_req {
|
||||
@ -633,7 +605,6 @@ struct se_dev_attrib {
|
||||
int emulate_tas;
|
||||
int emulate_tpu;
|
||||
int emulate_tpws;
|
||||
int emulate_reservations;
|
||||
int emulate_alua;
|
||||
int enforce_pr_isids;
|
||||
int is_nonrot;
|
||||
|
Loading…
Reference in New Issue
Block a user