Commit 0dfc00b6 authored by Nicholas Bellinger's avatar Nicholas Bellinger Committed by Luis Henriques

target: Fix R_HOLDER bit usage for AllRegistrants

commit d16ca7c5 upstream.

This patch fixes the usage of R_HOLDER bit for an All Registrants
reservation in READ_FULL_STATUS, where only the registration who
issued RESERVE was being reported as having an active reservation.

It changes core_scsi3_pri_read_full_status() to check ahead of the
list walk of active registrations to see if All Registrants is active,
and if so set R_HOLDER bit and scope/type fields for all active
registrations.
Reported-by: default avatarIlias Tsitsimpis <i.tsitsimpis@gmail.com>
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent eb506382
...@@ -3855,7 +3855,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) ...@@ -3855,7 +3855,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
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, desc_len, exp_desc_len;
u32 off = 8; /* off into first Full Status descriptor */ u32 off = 8; /* off into first Full Status descriptor */
int format_code = 0; int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
bool all_reg = false;
if (cmd->data_length < 8) { if (cmd->data_length < 8) {
pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
...@@ -3872,6 +3873,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) ...@@ -3872,6 +3873,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
buf[3] = (dev->t10_pr.pr_generation & 0xff); buf[3] = (dev->t10_pr.pr_generation & 0xff);
spin_lock(&dev->dev_reservation_lock);
if (dev->dev_pr_res_holder) {
struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder;
if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) {
all_reg = true;
pr_res_type = pr_holder->pr_res_type;
pr_res_scope = pr_holder->pr_res_scope;
}
}
spin_unlock(&dev->dev_reservation_lock);
spin_lock(&pr_tmpl->registration_lock); spin_lock(&pr_tmpl->registration_lock);
list_for_each_entry_safe(pr_reg, pr_reg_tmp, list_for_each_entry_safe(pr_reg, pr_reg_tmp,
&pr_tmpl->registration_list, pr_reg_list) { &pr_tmpl->registration_list, pr_reg_list) {
...@@ -3921,14 +3935,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) ...@@ -3921,14 +3935,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
* reservation holder for PR_HOLDER bit. * reservation holder for PR_HOLDER bit.
* *
* Also, if this registration is the reservation * Also, if this registration is the reservation
* holder, fill in SCOPE and TYPE in the next byte. * holder or there is an All Registrants reservation
* active, fill in SCOPE and TYPE in the next byte.
*/ */
if (pr_reg->pr_res_holder) { if (pr_reg->pr_res_holder) {
buf[off++] |= 0x01; buf[off++] |= 0x01;
buf[off++] = (pr_reg->pr_res_scope & 0xf0) | buf[off++] = (pr_reg->pr_res_scope & 0xf0) |
(pr_reg->pr_res_type & 0x0f); (pr_reg->pr_res_type & 0x0f);
} else } else if (all_reg) {
buf[off++] |= 0x01;
buf[off++] = (pr_res_scope & 0xf0) |
(pr_res_type & 0x0f);
} else {
off += 2; off += 2;
}
off += 4; /* Skip over reserved area */ off += 4; /* Skip over reserved area */
/* /*
......
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