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; 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, struct se_portal_group *se_tpg,
char *buf, char *buf,
u32 *out_tid_len, u32 *out_tid_len,
char **port_nexus_ptr) char **port_nexus_ptr,
char *i_str)
{ {
char *p; char *p;
int i; int i;
@ -282,7 +312,7 @@ static char *iscsi_parse_pr_out_transport_id(
if ((format_code != 0x00) && (format_code != 0x40)) { if ((format_code != 0x00) && (format_code != 0x40)) {
pr_err("Illegal format code: 0x%02x for iSCSI" pr_err("Illegal format code: 0x%02x for iSCSI"
" Initiator Transport ID\n", format_code); " Initiator Transport ID\n", format_code);
return NULL; return false;
} }
/* /*
* If the caller wants the TransportID Length, we set that value for the * 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" pr_err("Unable to locate \",i,0x\" separator"
" for Initiator port identifier: %s\n", " for Initiator port identifier: %s\n",
&buf[4]); &buf[4]);
return NULL; return false;
} }
*p = '\0'; /* Terminate iSCSI Name */ *p = '\0'; /* Terminate iSCSI Name */
p += 5; /* Skip over ",i,0x" separator */ p += 5; /* Skip over ",i,0x" separator */
@ -339,7 +369,8 @@ static char *iscsi_parse_pr_out_transport_id(
} else } else
*port_nexus_ptr = NULL; *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, 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, bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr) char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str)
{ {
u32 offset;
switch (tpg->proto_id) { switch (tpg->proto_id) {
case SCSI_PROTOCOL_SAS: case SCSI_PROTOCOL_SAS:
/* /*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID * Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
* for initiator ports using SCSI over SAS Serial SCSI Protocol. * 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; break;
case SCSI_PROTOCOL_SBP: case SCSI_PROTOCOL_SBP:
case SCSI_PROTOCOL_SRP: sbp_parse_pr_out_transport_id(buf, i_str);
case SCSI_PROTOCOL_FCP:
offset = 8;
break; break;
case SCSI_PROTOCOL_ISCSI: case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len, return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
port_nexus_ptr); port_nexus_ptr, i_str);
default: default:
pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id); pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
return NULL; return false;
} }
*port_nexus_ptr = NULL; *port_nexus_ptr = NULL;
*out_tid_len = 24; *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, int target_get_pr_transport_id(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code, struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf); unsigned char *buf);
const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg, bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
char *buf, u32 *out_tid_len, char **port_nexus_ptr); char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str);
/* target_core_hba.c */ /* target_core_hba.c */
struct se_hba *core_alloc_hba(const char *, u32, u32); 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); LIST_HEAD(tid_dest_list);
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
unsigned char *buf, *ptr, proto_ident; 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]; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret; sense_reason_t ret;
u32 tpdl, tid_len = 0; u32 tpdl, tid_len = 0;
u32 dest_rtpi = 0; u32 dest_rtpi = 0;
bool tid_found;
/* /*
* Allocate a struct pr_transport_id_holder and setup the * 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; dest_rtpi = tmp_lun->lun_rtpi;
iport_ptr = NULL; iport_ptr = NULL;
i_str = target_parse_pr_out_transport_id(tmp_tpg, tid_found = target_parse_pr_out_transport_id(tmp_tpg,
ptr, &tid_len, &iport_ptr); ptr, &tid_len, &iport_ptr, i_str);
if (!i_str) if (!tid_found)
continue; continue;
/* /*
* Determine if this SCSI device server requires that * 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_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
struct t10_reservation *pr_tmpl = &dev->t10_pr; struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf; 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] = { }; char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { };
u32 tid_len, tmp_tid_len; u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, matching_iname; int new_reg = 0, type, scope, matching_iname;
sense_reason_t ret; sense_reason_t ret;
unsigned short rtpi; unsigned short rtpi;
unsigned char proto_ident; unsigned char proto_ident;
bool tid_found;
if (!se_sess || !se_lun) { if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n"); 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; ret = TCM_INVALID_PARAMETER_LIST;
goto out; goto out;
} }
initiator_str = target_parse_pr_out_transport_id(dest_se_tpg, tid_found = target_parse_pr_out_transport_id(dest_se_tpg,
&buf[24], &tmp_tid_len, &iport_ptr); &buf[24], &tmp_tid_len, &iport_ptr, initiator_str);
if (!initiator_str) { if (!tid_found) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate" pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" initiator_str from Transport ID\n"); " initiator_str from Transport ID\n");
ret = TCM_INVALID_PARAMETER_LIST; ret = TCM_INVALID_PARAMETER_LIST;