Commit b6932ee3 authored by Steven Allen's avatar Steven Allen Committed by Nicholas Bellinger

target: return CONFLICT only when SA key unmatched

PREEMPT (and PREEMPT AND ABORT) should return CONFLICT iff a specified
SERVICE ACTION RESERVATION KEY is specified and matches no existing
persistent reservation.

Without this patch, a PREEMPT will return CONFLICT if either all
reservations are held by the initiator (self preemption) or there is
nothing to preempt. According to the spec, both of these cases should
succeed.
Signed-off-by: default avatarSteven Allen <steven.allen@purestorage.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 3b726ae2
...@@ -2738,7 +2738,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2738,7 +2738,8 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
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; u32 pr_res_mapped_lun = 0;
int all_reg = 0, calling_it_nexus = 0, released_regs = 0; int all_reg = 0, calling_it_nexus = 0;
bool sa_res_key_unmatched = sa_res_key != 0;
int prh_type = 0, prh_scope = 0; int prh_type = 0, prh_scope = 0;
if (!se_sess) if (!se_sess)
...@@ -2813,6 +2814,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2813,6 +2814,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
if (!all_reg) { if (!all_reg) {
if (pr_reg->pr_res_key != sa_res_key) if (pr_reg->pr_res_key != sa_res_key)
continue; continue;
sa_res_key_unmatched = false;
calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0; calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
pr_reg_nacl = pr_reg->pr_reg_nacl; pr_reg_nacl = pr_reg->pr_reg_nacl;
...@@ -2820,7 +2822,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2820,7 +2822,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
__core_scsi3_free_registration(dev, pr_reg, __core_scsi3_free_registration(dev, pr_reg,
(preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
NULL, calling_it_nexus); NULL, calling_it_nexus);
released_regs++;
} else { } else {
/* /*
* Case for any existing all registrants type * Case for any existing all registrants type
...@@ -2838,6 +2839,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2838,6 +2839,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
if ((sa_res_key) && if ((sa_res_key) &&
(pr_reg->pr_res_key != sa_res_key)) (pr_reg->pr_res_key != sa_res_key))
continue; continue;
sa_res_key_unmatched = false;
calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0; calling_it_nexus = (pr_reg_n == pr_reg) ? 1 : 0;
if (calling_it_nexus) if (calling_it_nexus)
...@@ -2848,7 +2850,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2848,7 +2850,6 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
__core_scsi3_free_registration(dev, pr_reg, __core_scsi3_free_registration(dev, pr_reg,
(preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list : (preempt_type == PREEMPT_AND_ABORT) ? &preempt_and_abort_list :
NULL, 0); NULL, 0);
released_regs++;
} }
if (!calling_it_nexus) if (!calling_it_nexus)
core_scsi3_ua_allocate(pr_reg_nacl, core_scsi3_ua_allocate(pr_reg_nacl,
...@@ -2863,7 +2864,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key, ...@@ -2863,7 +2864,7 @@ core_scsi3_pro_preempt(struct se_cmd *cmd, int type, int scope, u64 res_key,
* registered reservation key, then the device server shall * registered reservation key, then the device server shall
* complete the command with RESERVATION CONFLICT status. * complete the command with RESERVATION CONFLICT status.
*/ */
if (!released_regs) { if (sa_res_key_unmatched) {
spin_unlock(&dev->dev_reservation_lock); spin_unlock(&dev->dev_reservation_lock);
core_scsi3_put_pr_reg(pr_reg_n); core_scsi3_put_pr_reg(pr_reg_n);
return TCM_RESERVATION_CONFLICT; return TCM_RESERVATION_CONFLICT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment