From: John Garry <john.g.garry@oracle.com>
To: Gulam Mohamed <gulam.mohamed@oracle.com>,
martin.petersen@oracle.com, linux-scsi@vger.kernel.org,
target-devel@vger.kernel.org
Subject: Re: [PATCH 6.19/scsi-queue] scsi: target: core: Add emulation for REPORT_IDENTIFICATION_INFORMATION
Date: Mon, 17 Nov 2025 16:19:28 +0000 [thread overview]
Message-ID: <b3c28b7f-503d-4e83-b4c2-b756150bfbd9@oracle.com> (raw)
In-Reply-To: <20251026191309.34968-1-gulam.mohamed@oracle.com>
On 26/10/2025 19:13, Gulam Mohamed wrote:
In the title, why "REPORT_IDENTIFICATION_INFORMATION" and not
"REPORT_IDENTIFYING_INFORMATION"?
> This patch
git grep "This patch" Documentation/process/
> will implement the REPORT_IDENTIFICATION_INFORMATION using the
> configfs file pd_text_id_info in target core module. The configfs file is
> created in /sys/kernel/config/target/core/<backend type>/
> <backing_store_name>/wwn/. The user can set the peripheral device text
> identification string to the file pd_text_id_info. An emulation function
> "spc_emulate_report_id_info()" is defined in target_core_spc.c which
> returns the device text id whenever the user requests the same.
It would be nice to a mention a spec reference for the command.
>
> Signed-off-by: Gulam Mohamed <gulam.mohamed@oracle.com>
Generally the code below looks ok, but I'll be nitpicking a bit...
> ---
> drivers/target/target_core_configfs.c | 55 ++++++++++++++++++
> drivers/target/target_core_spc.c | 82 +++++++++++++++++++++++++++
> include/target/target_core_base.h | 4 ++
> 3 files changed, 141 insertions(+)
>
> diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
> index b19acd662726..ac78a106e0f3 100644
> --- a/drivers/target/target_core_configfs.c
> +++ b/drivers/target/target_core_configfs.c
> @@ -1726,6 +1726,59 @@ static ssize_t target_wwn_vpd_protocol_identifier_show(struct config_item *item,
> return len;
> }
>
> +static ssize_t target_wwn_pd_text_id_info_show(struct config_item *item,
> + char *page)
> +{
> + return sprintf(page, "%s\n", &to_t10_wwn(item)->pd_text_id_info[0]);
> +}
> +
> +static ssize_t target_wwn_pd_text_id_info_store(struct config_item *item,
> + const char *page, size_t count)
> +{
> + struct t10_wwn *t10_wwn = to_t10_wwn(item);
> + struct se_device *dev = t10_wwn->t10_dev;
> +
> + /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
> + unsigned char buf[PD_TEXT_ID_INFO_LEN + 2];
> + char *stripped = NULL;
> + ssize_t len;
> +
> + len = strscpy(buf, page, sizeof(buf));
> + if (len > 0) {
Can you just return early if len is too short?
> + /* Strip any newline added from userspace. */
> + stripped = strstrip(buf);
> + len = strlen(stripped);
> + }
> +
> + if (len < 0 || len >= PD_TEXT_ID_INFO_LEN) {
> + pr_err("Emulated peripheral device text id info exceeds"
> + " PD_TEXT_ID_INFO_LEN: " __stringify(PD_TEXT_ID_INFO_LEN)
> + "\n");
I think that this can all be a single line.
> + return -EOVERFLOW;
> + }
> +
> + /*
> + * Check to see if any active exports exist. If they do exist, fail
> + * here as changing this information on the fly (underneath the
> + * initiator side OS dependent multipath code) could cause negative
> + * effects.
> + */
> + if (dev->export_count) {
I would check this before any of the string correctness
> + pr_err("Unable to set the peripheral device text id info while"
> + " active %d exports exist\n", dev->export_count);
I think that the following is better, i.e. keep fixed strings on same
line to make grep'ing easier:
pr_err("Unable to set the peripheral device text id info while active %d
exports exist\n",
dev->export_count);
> + return -EINVAL;
> + }
> +
> + BUILD_BUG_ON(sizeof(dev->t10_wwn.pd_text_id_info) != PD_TEXT_ID_INFO_LEN);
> + strscpy(dev->t10_wwn.pd_text_id_info, stripped,
> + sizeof(dev->t10_wwn.pd_text_id_info));
> +
> + pr_debug("Target_Core_ConfigFS: Set emulated peripheral dev text id info:"
> + " %s\n", dev->t10_wwn.pd_text_id_info);
> +
> + return count;
> +}
> +
> /*
> * Generic wrapper for dumping VPD identifiers by association.
> */
> @@ -1782,6 +1835,7 @@ CONFIGFS_ATTR_RO(target_wwn_, vpd_protocol_identifier);
> CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_logical_unit);
> CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_target_port);
> CONFIGFS_ATTR_RO(target_wwn_, vpd_assoc_scsi_target_device);
> +CONFIGFS_ATTR(target_wwn_, pd_text_id_info);
>
> static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
> &target_wwn_attr_vendor_id,
> @@ -1793,6 +1847,7 @@ static struct configfs_attribute *target_core_dev_wwn_attrs[] = {
> &target_wwn_attr_vpd_assoc_logical_unit,
> &target_wwn_attr_vpd_assoc_target_port,
> &target_wwn_attr_vpd_assoc_scsi_target_device,
> + &target_wwn_attr_pd_text_id_info,
> NULL,
> };
>
> diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
> index aad0096afa21..9fa84202ee4b 100644
> --- a/drivers/target/target_core_spc.c
> +++ b/drivers/target/target_core_spc.c
> @@ -1963,6 +1963,18 @@ static const struct target_opcode_descriptor tcm_opcode_report_supp_opcodes = {
> .enabled = spc_rsoc_enabled,
> };
>
> +static struct target_opcode_descriptor tcm_opcode_report_identifying_information = {
> + .support = SCSI_SUPPORT_FULL,
> + .serv_action_valid = 1,
> + .opcode = MAINTENANCE_IN,
> + .service_action = MI_REPORT_IDENTIFYING_INFORMATION,
> + .cdb_size = 12,
> + .usage_bits = {MAINTENANCE_IN, MI_REPORT_IDENTIFYING_INFORMATION,
> + 0x00, 0x00,
> + 0x00, 0x00, 0xff, 0xff,
> + 0xff, 0xff, 0xff, SCSI_CONTROL_MASK},
> +};
> +
> static bool tcm_is_set_tpg_enabled(const struct target_opcode_descriptor *descr,
> struct se_cmd *cmd)
> {
> @@ -2049,6 +2061,7 @@ static const struct target_opcode_descriptor *tcm_supported_opcodes[] = {
> &tcm_opcode_report_target_pgs,
> &tcm_opcode_report_supp_opcodes,
> &tcm_opcode_set_tpg,
> + &tcm_opcode_report_identifying_information,
> };
>
> static int
> @@ -2266,6 +2279,70 @@ spc_emulate_report_supp_op_codes(struct se_cmd *cmd)
> return ret;
> }
>
> +static sense_reason_t
> +spc_fill_pd_text_id_info(struct se_cmd *cmd, u8 *cdb)
> +{
> + struct se_device *dev = cmd->se_dev;
> + unsigned char *buf;
> + unsigned char *rbuf;
> + u32 header_len = 4;
> + u32 actual_data_len;
> + u32 buf_len;
> + u16 id_len;
> +
> + buf_len = get_unaligned_be32(&cdb[6]);
> + if (buf_len < header_len)
> + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
isn't there a limit of 512 bytes for code 10b?
> +> + id_len = strlen(dev->t10_wwn.pd_text_id_info);
> + if (id_len > 0)
> + /* trailing null */
> + id_len += 1;
> +
> + actual_data_len = id_len + header_len;
> +
> + if (actual_data_len < buf_len)
> + buf_len = actual_data_len;
> +
> + buf = kzalloc(buf_len, GFP_KERNEL);
> + if (!buf) {
> + pr_err("Unable to allocate response buffer for IDENTITY INFO\n");
> + return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
> + }
> +
> + scnprintf(&buf[header_len], buf_len - header_len, "%s",
> + dev->t10_wwn.pd_text_id_info);
> +
> + put_unaligned_be16(id_len, &buf[2]);
> +
> + rbuf = transport_kmap_data_sg(cmd);
is it really ok if this returns NULL?
> + if (rbuf) {
> + memcpy(rbuf, buf, buf_len);
> + transport_kunmap_data_sg(cmd);
> + }
> + kfree(buf);
> +
> + target_complete_cmd_with_length(cmd, SAM_STAT_GOOD, buf_len);
> + return TCM_NO_SENSE;
> +}
> +
> +static sense_reason_t
> +spc_emulate_report_id_info(struct se_cmd *cmd)
> +{
> + u8 *cdb = cmd->t_task_cdb;
> + sense_reason_t rc;
> +
> + switch ((cdb[10] >> 1)) {
> + case 2:
> + rc = spc_fill_pd_text_id_info(cmd, cdb);
> + break;
> + default:
> + return TCM_UNSUPPORTED_SCSI_OPCODE;
> + }
> +
> + return rc;
I don't know why default clause is required and not return result from
spc_fill_pd_text_id_info() directly?
> +}
> +
> sense_reason_t
> spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
> {
> @@ -2405,6 +2482,11 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
> MI_REPORT_SUPPORTED_OPERATION_CODES)
> cmd->execute_cmd =
> spc_emulate_report_supp_op_codes;
> + if ((cdb[1] & 0x1f) ==
> + MI_REPORT_IDENTIFYING_INFORMATION) {
> + cmd->execute_cmd =
> + spc_emulate_report_id_info;
> + }
> *size = get_unaligned_be32(&cdb[6]);
> } else {
> /*
> diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
> index c4d9116904aa..c9b5edcce1eb 100644
> --- a/include/target/target_core_base.h
> +++ b/include/target/target_core_base.h
> @@ -108,6 +108,9 @@
> #define SE_MODE_PAGE_BUF 512
> #define SE_SENSE_BUF 96
>
> +/* Peripheral Device Text Identification Information */
> +#define PD_TEXT_ID_INFO_LEN 256
as above, I thought that it was 512 bytes
> +
> enum target_submit_type {
> /* Use the fabric driver's default submission type */
> TARGET_FABRIC_DEFAULT_SUBMIT,
> @@ -347,6 +350,7 @@ struct t10_wwn {
> struct se_device *t10_dev;
> struct config_group t10_wwn_group;
> struct list_head t10_vpd_list;
> + char pd_text_id_info[PD_TEXT_ID_INFO_LEN];
> };
>
> struct t10_pr_registration {
next prev parent reply other threads:[~2025-11-17 16:19 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-26 19:13 [PATCH 6.19/scsi-queue] scsi: target: core: Add emulation for REPORT_IDENTIFICATION_INFORMATION Gulam Mohamed
2025-11-17 16:19 ` John Garry [this message]
2025-11-19 19:58 ` Gulam Mohamed
2025-11-25 18:01 ` Mike Christie
2025-11-26 11:53 ` John Garry
2025-11-27 9:27 ` Gulam Mohamed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b3c28b7f-503d-4e83-b4c2-b756150bfbd9@oracle.com \
--to=john.g.garry@oracle.com \
--cc=gulam.mohamed@oracle.com \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox