aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2014-12-14 04:47:19 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2014-12-15 23:38:33 -0500
commitd16ca7c5198fd668db10d2c7b048ed3359c12c54 (patch)
tree84f8eafe8c51c3489634ec1d34cea209c74cda7f
parentee8e3ad96e04749aa043c7fcb7fe6a562f8b9c48 (diff)
target: Fix R_HOLDER bit usage for AllRegistrants
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: Ilias Tsitsimpis <i.tsitsimpis@gmail.com> Cc: James Bottomley <James.Bottomley@HansenPartnership.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_pr.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index f91b6a1b846e..c4a8da5415c5 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -3834,7 +3834,8 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
3834 unsigned char *buf; 3834 unsigned char *buf;
3835 u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len; 3835 u32 add_desc_len = 0, add_len = 0, desc_len, exp_desc_len;
3836 u32 off = 8; /* off into first Full Status descriptor */ 3836 u32 off = 8; /* off into first Full Status descriptor */
3837 int format_code = 0; 3837 int format_code = 0, pr_res_type = 0, pr_res_scope = 0;
3838 bool all_reg = false;
3838 3839
3839 if (cmd->data_length < 8) { 3840 if (cmd->data_length < 8) {
3840 pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u" 3841 pr_err("PRIN SA READ_FULL_STATUS SCSI Data Length: %u"
@@ -3851,6 +3852,19 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
3851 buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff); 3852 buf[2] = ((dev->t10_pr.pr_generation >> 8) & 0xff);
3852 buf[3] = (dev->t10_pr.pr_generation & 0xff); 3853 buf[3] = (dev->t10_pr.pr_generation & 0xff);
3853 3854
3855 spin_lock(&dev->dev_reservation_lock);
3856 if (dev->dev_pr_res_holder) {
3857 struct t10_pr_registration *pr_holder = dev->dev_pr_res_holder;
3858
3859 if (pr_holder->pr_res_type == PR_TYPE_WRITE_EXCLUSIVE_ALLREG ||
3860 pr_holder->pr_res_type == PR_TYPE_EXCLUSIVE_ACCESS_ALLREG) {
3861 all_reg = true;
3862 pr_res_type = pr_holder->pr_res_type;
3863 pr_res_scope = pr_holder->pr_res_scope;
3864 }
3865 }
3866 spin_unlock(&dev->dev_reservation_lock);
3867
3854 spin_lock(&pr_tmpl->registration_lock); 3868 spin_lock(&pr_tmpl->registration_lock);
3855 list_for_each_entry_safe(pr_reg, pr_reg_tmp, 3869 list_for_each_entry_safe(pr_reg, pr_reg_tmp,
3856 &pr_tmpl->registration_list, pr_reg_list) { 3870 &pr_tmpl->registration_list, pr_reg_list) {
@@ -3898,14 +3912,20 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd)
3898 * reservation holder for PR_HOLDER bit. 3912 * reservation holder for PR_HOLDER bit.
3899 * 3913 *
3900 * Also, if this registration is the reservation 3914 * Also, if this registration is the reservation
3901 * holder, fill in SCOPE and TYPE in the next byte. 3915 * holder or there is an All Registrants reservation
3916 * active, fill in SCOPE and TYPE in the next byte.
3902 */ 3917 */
3903 if (pr_reg->pr_res_holder) { 3918 if (pr_reg->pr_res_holder) {
3904 buf[off++] |= 0x01; 3919 buf[off++] |= 0x01;
3905 buf[off++] = (pr_reg->pr_res_scope & 0xf0) | 3920 buf[off++] = (pr_reg->pr_res_scope & 0xf0) |
3906 (pr_reg->pr_res_type & 0x0f); 3921 (pr_reg->pr_res_type & 0x0f);
3907 } else 3922 } else if (all_reg) {
3923 buf[off++] |= 0x01;
3924 buf[off++] = (pr_res_scope & 0xf0) |
3925 (pr_res_type & 0x0f);
3926 } else {
3908 off += 2; 3927 off += 2;
3928 }
3909 3929
3910 off += 4; /* Skip over reserved area */ 3930 off += 4; /* Skip over reserved area */
3911 /* 3931 /*