| From: David Disseldorp <ddiss@suse.de> |
| Date: Tue, 19 Jun 2018 17:58:24 +0200 |
| Subject: scsi: target: Fix truncated PR-in ReadKeys response |
| |
| commit 63ce3c384db26494615e3c8972bcd419ed71f4c4 upstream. |
| |
| SPC5r17 states that the contents of the ADDITIONAL LENGTH field are not |
| altered based on the allocation length, so always calculate and pack the |
| full key list length even if the list itself is truncated. |
| |
| According to Maged: |
| |
| Yes it fixes the "Storage Spaces Persistent Reservation" test in the |
| Windows 2016 Server Failover Cluster validation suites when having |
| many connections that result in more than 8 registrations. I tested |
| your patch on 4.17 with iblock. |
| |
| This behaviour can be tested using the libiscsi PrinReadKeys.Truncate test. |
| |
| Signed-off-by: David Disseldorp <ddiss@suse.de> |
| Reviewed-by: Mike Christie <mchristi@redhat.com> |
| Tested-by: Maged Mokhtar <mmokhtar@petasan.org> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| [bwh: Backported to 3.16: Convert from open-coded put_unaligned_be64()] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/target/target_core_pr.c | 15 ++++++++++----- |
| 1 file changed, 10 insertions(+), 5 deletions(-) |
| |
| --- a/drivers/target/target_core_pr.c |
| +++ b/drivers/target/target_core_pr.c |
| @@ -3726,18 +3726,16 @@ core_scsi3_pri_read_keys(struct se_cmd * |
| * Check for overflow of 8byte PRI READ_KEYS payload and |
| * next reservation key list descriptor. |
| */ |
| - if ((add_len + 8) > (cmd->data_length - 8)) |
| - break; |
| - |
| - buf[off++] = ((pr_reg->pr_res_key >> 56) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 48) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 40) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 32) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 24) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 16) & 0xff); |
| - buf[off++] = ((pr_reg->pr_res_key >> 8) & 0xff); |
| - buf[off++] = (pr_reg->pr_res_key & 0xff); |
| - |
| + if (off + 8 <= cmd->data_length) { |
| + put_unaligned_be64(pr_reg->pr_res_key, &buf[off]); |
| + off += 8; |
| + } |
| + /* |
| + * SPC5r17: 6.16.2 READ KEYS service action |
| + * The ADDITIONAL LENGTH field indicates the number of bytes in |
| + * the Reservation key list. The contents of the ADDITIONAL |
| + * LENGTH field are not altered based on the allocation length |
| + */ |
| add_len += 8; |
| } |
| spin_unlock(&dev->t10_pr.registration_lock); |