scsi: target: core: Generate correct identifiers for PR OUT transport IDs

[ Upstream commit 6e0f6aa44b ]

Fix target_parse_pr_out_transport_id() to return a string representing
the transport ID in a human-readable format (e.g., naa.xxxxxxxx...)  for
various SCSI protocol types (SAS, FCP, SRP, SBP).

Previously, the function returned a pointer to the raw binary buffer,
which was incorrectly compared against human-readable strings, causing
comparisons to fail.  Now, the function writes a properly formatted
string into a buffer provided by the caller.  The output format depends
on the transport protocol:

* SAS: 64-bit identifier, "naa." prefix.
* FCP: 64-bit identifier, colon separated values.
* SBP: 64-bit identifier, no prefix.
* SRP: 128-bit identifier, "0x" prefix.
* iSCSI: IQN string.

Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Link: https://lore.kernel.org/r/20250714133738.11054-1-mlombard@redhat.com
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Maurizio Lombardi 2025-07-14 15:37:38 +02:00 committed by Greg Kroah-Hartman
parent d91b972513
commit 128107627a
3 changed files with 61 additions and 26 deletions

View File

@ -257,11 +257,41 @@ static int iscsi_get_pr_transport_id_len(
return len;
}
static char *iscsi_parse_pr_out_transport_id(
static void sas_parse_pr_out_transport_id(char *buf, char *i_str)
{
char hex[17] = {};
bin2hex(hex, buf + 4, 8);
snprintf(i_str, TRANSPORT_IQN_LEN, "naa.%s", hex);
}
static void srp_parse_pr_out_transport_id(char *buf, char *i_str)
{
char hex[33] = {};
bin2hex(hex, buf + 8, 16);
snprintf(i_str, TRANSPORT_IQN_LEN, "0x%s", hex);
}
static void fcp_parse_pr_out_transport_id(char *buf, char *i_str)
{
snprintf(i_str, TRANSPORT_IQN_LEN, "%8phC", buf + 8);
}
static void sbp_parse_pr_out_transport_id(char *buf, char *i_str)
{
char hex[17] = {};
bin2hex(hex, buf + 8, 8);
snprintf(i_str, TRANSPORT_IQN_LEN, "%s", hex);
}
static bool iscsi_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
char *buf,
u32 *out_tid_len,
char **port_nexus_ptr)
char **port_nexus_ptr,
char *i_str)
{
char *p;
int i;
@ -282,7 +312,7 @@ static char *iscsi_parse_pr_out_transport_id(
if ((format_code != 0x00) && (format_code != 0x40)) {
pr_err("Illegal format code: 0x%02x for iSCSI"
" Initiator Transport ID\n", format_code);
return NULL;
return false;
}
/*
* If the caller wants the TransportID Length, we set that value for the
@ -306,7 +336,7 @@ static char *iscsi_parse_pr_out_transport_id(
pr_err("Unable to locate \",i,0x\" separator"
" for Initiator port identifier: %s\n",
&buf[4]);
return NULL;
return false;
}
*p = '\0'; /* Terminate iSCSI Name */
p += 5; /* Skip over ",i,0x" separator */
@ -339,7 +369,8 @@ static char *iscsi_parse_pr_out_transport_id(
} else
*port_nexus_ptr = NULL;
return &buf[4];
strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN);
return true;
}
int target_get_pr_transport_id_len(struct se_node_acl *nacl,
@ -387,33 +418,35 @@ int target_get_pr_transport_id(struct se_node_acl *nacl,
}
}
const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr)
bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str)
{
u32 offset;
switch (tpg->proto_id) {
case SCSI_PROTOCOL_SAS:
/*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
* for initiator ports using SCSI over SAS Serial SCSI Protocol.
*/
offset = 4;
sas_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_SRP:
srp_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_FCP:
fcp_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_SBP:
case SCSI_PROTOCOL_SRP:
case SCSI_PROTOCOL_FCP:
offset = 8;
sbp_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
port_nexus_ptr);
port_nexus_ptr, i_str);
default:
pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
return NULL;
return false;
}
*port_nexus_ptr = NULL;
*out_tid_len = 24;
return buf + offset;
return true;
}

View File

@ -104,8 +104,8 @@ int target_get_pr_transport_id_len(struct se_node_acl *nacl,
int target_get_pr_transport_id(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf);
const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr);
bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str);
/* target_core_hba.c */
struct se_hba *core_alloc_hba(const char *, u32, u32);

View File

@ -1477,11 +1477,12 @@ core_scsi3_decode_spec_i_port(
LIST_HEAD(tid_dest_list);
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
unsigned char *buf, *ptr, proto_ident;
const unsigned char *i_str = NULL;
unsigned char i_str[TRANSPORT_IQN_LEN];
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret;
u32 tpdl, tid_len = 0;
u32 dest_rtpi = 0;
bool tid_found;
/*
* Allocate a struct pr_transport_id_holder and setup the
@ -1570,9 +1571,9 @@ core_scsi3_decode_spec_i_port(
dest_rtpi = tmp_lun->lun_rtpi;
iport_ptr = NULL;
i_str = target_parse_pr_out_transport_id(tmp_tpg,
ptr, &tid_len, &iport_ptr);
if (!i_str)
tid_found = target_parse_pr_out_transport_id(tmp_tpg,
ptr, &tid_len, &iport_ptr, i_str);
if (!tid_found)
continue;
/*
* Determine if this SCSI device server requires that
@ -3152,13 +3153,14 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf;
const unsigned char *initiator_str;
unsigned char initiator_str[TRANSPORT_IQN_LEN];
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { };
u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, matching_iname;
sense_reason_t ret;
unsigned short rtpi;
unsigned char proto_ident;
bool tid_found;
if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
@ -3277,9 +3279,9 @@ core_scsi3_emulate_pro_register_and_move(struct se_cmd *cmd, u64 res_key,
ret = TCM_INVALID_PARAMETER_LIST;
goto out;
}
initiator_str = target_parse_pr_out_transport_id(dest_se_tpg,
&buf[24], &tmp_tid_len, &iport_ptr);
if (!initiator_str) {
tid_found = target_parse_pr_out_transport_id(dest_se_tpg,
&buf[24], &tmp_tid_len, &iport_ptr, initiator_str);
if (!tid_found) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" initiator_str from Transport ID\n");
ret = TCM_INVALID_PARAMETER_LIST;