diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-12-14 04:47:19 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-12-15 23:38:33 -0500 |
commit | d16ca7c5198fd668db10d2c7b048ed3359c12c54 (patch) | |
tree | 84f8eafe8c51c3489634ec1d34cea209c74cda7f | |
parent | ee8e3ad96e04749aa043c7fcb7fe6a562f8b9c48 (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.c | 26 |
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 | /* |