From: Bart Van Assche <bvanassche@acm.org>
To: James Smart <jsmart2021@gmail.com>, linux-scsi@vger.kernel.org
Cc: maier@linux.ibm.com, dwagner@suse.de,
Ram Vegesna <ram.vegesna@broadcom.com>
Subject: Re: [PATCH v2 24/32] elx: efct: LIO backend interface routines
Date: Wed, 8 Jan 2020 19:56:08 -0800 [thread overview]
Message-ID: <a1c547a3-f5b8-54bc-b9e9-5b0ad0786ed3@acm.org> (raw)
In-Reply-To: <20191220223723.26563-25-jsmart2021@gmail.com>
On 2019-12-20 14:37, James Smart wrote:
> +#include <scsi/scsi_tcq.h>
Including the scsi_tcq.h header file is only useful in source files that
implement initiator functionality. This source file implements SCSI
target functionality. Is this include really necessary?
> +static struct workqueue_struct *lio_wq;
> +
> +static int
> +efct_format_wwn(char *str, size_t len, char *pre, u64 wwn)
> +{
> + u8 a[8];
> +
> + put_unaligned_be64(wwn, a);
> + return snprintf(str, len,
> + "%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
> + pre, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
> +}
Can the type of 'pre' be changed from 'char *' into 'const char *'?
Can %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x be changed into %8phC?
> +static int
> +efct_lio_parse_wwn(const char *name, u64 *wwp, u8 npiv)
> +{
> + int a[8], num;
> + u8 b[8];
> +
> + if (npiv) {
> + num = sscanf(name, "%02x%02x%02x%02x%02x%02x%02x%02x",
> + &a[0], &a[1], &a[2], &a[3], &a[4],
> + &a[5], &a[6], &a[7]);
> + } else {
> + num = sscanf(name,
> + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
> + &a[0], &a[1], &a[2], &a[3], &a[4],
> + &a[5], &a[6], &a[7]);
> + }
> +
> + if (num != 8)
> + return -EINVAL;
> +
> + for (num = 0; num < 8; ++num)
> + b[num] = (u8) a[num];
> +
> + *wwp = get_unaligned_be64(b);
> + return 0;
> +}
If the %02x sscanf specifiers are changed into %02hhx, can the int a[8]
array be left out?
> +static ssize_t
> +efct_lio_npiv_tpg_enable_store(struct config_item *item, const char *page,
> + size_t count)
> +{
> + struct se_portal_group *se_tpg = to_tpg(item);
> + struct efct_lio_tpg *tpg = container_of(se_tpg,
> + struct efct_lio_tpg, tpg);
> + struct efct_lio_vport *lio_vport = tpg->vport;
> + struct efct_lio_vport_data_t *vport_data;
> + struct efct *efct;
> + struct efc *efc;
> + int ret = -1;
> + unsigned long op, flags = 0;
> +
> + if (kstrtoul(page, 0, &op) < 0)
> + return -EINVAL;
> +
> + if (!lio_vport) {
> + pr_err("Unable to find vport\n");
> + return -EINVAL;
> + }
> +
> + efct = lio_vport->efct;
> + efc = efct->efcport;
> +
> + if (op == 1) {
> + atomic_set(&tpg->enabled, 1);
> + efc_log_debug(efct, "enable portal group %d\n", tpg->tpgt);
> +
> + if (efc->domain) {
> + ret = efc_sport_vport_new(efc->domain,
> + lio_vport->npiv_wwpn,
> + lio_vport->npiv_wwnn,
> + U32_MAX, false, true,
> + NULL, NULL, true);
> + if (ret != 0) {
> + efc_log_err(efct, "Failed to create Vport\n");
> + return ret;
> + }
> + return count;
> + }
> +
> + vport_data = kmalloc(sizeof(*vport_data), GFP_KERNEL);
> + if (!vport_data)
> + return ret;
> +
> + memset(vport_data, 0, sizeof(struct efct_lio_vport_data_t));
> + vport_data->phy_wwpn = lio_vport->wwpn;
> + vport_data->vport_wwpn = lio_vport->npiv_wwpn;
> + vport_data->vport_wwnn = lio_vport->npiv_wwnn;
> + vport_data->target_mode = 1;
> + vport_data->initiator_mode = 0;
> + vport_data->lio_vport = lio_vport;
> +
> + /* There is no domain. Add to pending list. When the
> + * domain is created, the driver will create the vport.
> + */
> + efc_log_debug(efct, "link down, move to pending\n");
> + spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);
> + INIT_LIST_HEAD(&vport_data->list_entry);
> + list_add_tail(&vport_data->list_entry,
> + &efct->tgt_efct.vport_pend_list);
> + spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);
> +
> + } else if (op == 0) {
> + struct efct_lio_vport_data_t *virt_target_data, *next;
> +
> + efc_log_debug(efct, "disable portal group %d\n", tpg->tpgt);
> +
> + atomic_set(&tpg->enabled, 0);
> + /* only physical sport should exist, free lio_sport
> + * allocated in efct_lio_make_sport
> + */
> + if (efc->domain) {
> + efc_sport_vport_del(efct->efcport, efc->domain,
> + lio_vport->npiv_wwpn,
> + lio_vport->npiv_wwnn);
> + return count;
> + }
> + spin_lock_irqsave(&efct->tgt_efct.efct_lio_lock, flags);
> + list_for_each_entry_safe(virt_target_data, next,
> + &efct->tgt_efct.vport_pend_list,
> + list_entry) {
> + if (virt_target_data->lio_vport == lio_vport) {
> + list_del(&virt_target_data->list_entry);
> + kfree(virt_target_data);
> + break;
> + }
> + }
> + spin_unlock_irqrestore(&efct->tgt_efct.efct_lio_lock, flags);
> + } else {
> + return -EINVAL;
> + }
> + return count;
> +}
I think the above function can return -1. Please make sure that this
function returns an appropriate error code if something fails.
> +static bool efct_lio_node_is_initiator(struct efc_node *node)
> +{
> + if (!node)
> + return 0;
> +
> + if (node->rnode.fc_id && node->rnode.fc_id != FC_FID_FLOGI &&
> + node->rnode.fc_id != FC_FID_DIR_SERV &&
> + node->rnode.fc_id != FC_FID_FCTRL) {
> + return 1;
> + }
> +
> + return 0;
> +}
Should return 0 / return 1 perhaps be changed into return false / return
true?
> +static int efct_lio_tgt_session_data(struct efct *efct, u64 wwpn,
> + char *buf, int size)
> +{
> + struct efc_sli_port *sport = NULL;
> + struct efc_node *node = NULL;
> + struct efc *efc = efct->efcport;
> + u16 loop_id = 0;
> + int off = 0, rc = 0;
> +
> + if (!efc->domain) {
> + efc_log_err(efct, "failed to find efct/domain\n");
> + return -1;
> + }
> +
> + list_for_each_entry(sport, &efc->domain->sport_list, list_entry) {
> + if (sport->wwpn != wwpn)
> + continue;
> + list_for_each_entry(node, &sport->node_list,
> + list_entry) {
> + /* Dump only remote NPORT sessions */
> + if (!efct_lio_node_is_initiator(node))
> + continue;
> +
> + rc = snprintf(buf + off, size - off,
> + "0x%016llx,0x%08x,0x%04x\n",
> + get_unaligned_be64(node->wwpn),
> + node->rnode.fc_id, loop_id);
> + if (rc < 0)
> + break;
> + off += rc;
> + }
> + }
> +
> + buf[size - 1] = '\0';
> + return 0;
> +}
Does the caller of this function initialize buf[]? If not, should this
function initialize buf[] before calling snprintf()?
Since snprintf() guarantees '\0' termination I think that the buf[size -
1] = '\0' at the end of this function can be left out.
> +static int
> +efct_lio_datamove_done(struct efct_io *io, enum efct_scsi_io_status scsi_status,
> + u32 flags, void *arg);
Can this forward declaration be avoided by reordering the function
definitions?
> +static struct se_wwn *
> +efct_lio_npiv_make_sport(struct target_fabric_configfs *tf,
> + struct config_group *group, const char *name)
> +{
> + struct efct_lio_vport *lio_vport;
> + struct efct *efct;
> + int ret = -1;
> + u64 p_wwpn, npiv_wwpn, npiv_wwnn;
> + char *p, tmp[128];
> + struct efct_lio_vport_list_t *vport_list;
> + struct fc_vport *new_fc_vport;
> + struct fc_vport_identifiers vport_id;
> + unsigned long flags = 0;
> +
> + snprintf(tmp, 128, "%s", name);
How about using sizeof(tmp) instead of hardcoding the array size?
> + p = strchr(tmp, '@');
> +
> + if (!p) {
> + pr_err("Unable to find separator operator(@)\n");
> + return ERR_PTR(ret);
> + }
> + *p++ = '\0';
Can this be changed into a strsep() call?
> +int efct_scsi_tgt_del_device(struct efct *efct)
> +{
> + int rc = 0;
> +
> + flush_workqueue(lio_wq);
> +
> + return rc;
> +}
Is the 'rc' variable necessary in the above function? Can it be removed?
> +/* Called by the libefc when an initiator goes away. */
> +int efct_scsi_del_initiator(struct efc *efc, struct efc_node *node,
> + int reason)
> +{
> + struct efct *efct = node->efc->base;
> + struct efct_lio_wq_data *wq_data;
> + int watermark;
> + int initiator_count;
> +
> + if (reason == EFCT_SCSI_INITIATOR_MISSING)
> + return EFCT_SCSI_CALL_COMPLETE;
> +
> + wq_data = kmalloc(sizeof(*wq_data), GFP_ATOMIC);
> + if (!wq_data)
> + return EFCT_SCSI_CALL_COMPLETE;
> +
> + memset(wq_data, 0, sizeof(*wq_data));
> + wq_data->ptr = node;
> + wq_data->efct = efct;
> + INIT_WORK(&wq_data->work, efct_lio_remove_session);
> + queue_work(lio_wq, &wq_data->work);
> +
> + /*
> + * update IO watermark: decrement initiator count
> + */
> + initiator_count =
> + atomic_sub_return(1, &efct->tgt_efct.initiator_count);
> + watermark = (efct->tgt_efct.watermark_max -
> + initiator_count * EFCT_IO_WATERMARK_PER_INITIATOR);
> + watermark = (efct->tgt_efct.watermark_min > watermark) ?
> + efct->tgt_efct.watermark_min : watermark;
> + atomic_set(&efct->tgt_efct.io_high_watermark, watermark);
> +
> + return EFCT_SCSI_CALL_ASYNC;
> +}
Is the lio_wq work queue really necessary? Could one of the system
workqueues have been used instead?
> + ret = kstrtoul(page, 0, &val); \
> + if (ret < 0) { \
> + pr_err("kstrtoul() failed with ret: %d\n", ret); \
> + return -EINVAL; \
> + } \
Has it been considered to return 'ret' (the kstrtoul() return value)
instead of -EINVAL?
> + ret = kstrtoul(page, 0, &val); \
> + if (ret < 0) { \
> + pr_err("kstrtoul() failed with ret: %d\n", ret); \
> + return -EINVAL; \
> + } \
Same comment here.
> +#define efct_set_lio_io_state(io, value) (io->tgt_io.state |= value)
Is this macro really useful? Can it be removed?
> +struct efct_scsi_tgt_io {
> + struct se_cmd cmd;
> + unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER];
> + int ddir;
Should 'int' perhaps be changed into 'enum dma_data_direction'?
> + u8 cdb_opcode;
Does this duplicate cmd.t_task_cdb[0]? If so, is it useful to duplicate
that value?
> + u32 cdb_len;
Is this value identical to scsi_command_size(cmd.t_task_cdb)? Is it
essential to have this member in this data structure?
Thanks,
Bart.
next prev parent reply other threads:[~2020-01-09 3:56 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-12-20 22:36 [PATCH v2 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver James Smart
2019-12-20 22:36 ` [PATCH v2 01/32] elx: libefc_sli: SLI-4 register offsets and field definitions James Smart
2020-01-08 7:11 ` Hannes Reinecke
2020-01-09 0:59 ` James Smart
2019-12-20 22:36 ` [PATCH v2 02/32] elx: libefc_sli: SLI Descriptors and Queue entries James Smart
2020-01-08 7:24 ` Hannes Reinecke
2020-01-09 1:00 ` James Smart
2019-12-20 22:36 ` [PATCH v2 03/32] elx: libefc_sli: Data structures and defines for mbox commands James Smart
2020-01-08 7:32 ` Hannes Reinecke
2020-01-09 1:03 ` James Smart
2019-12-20 22:36 ` [PATCH v2 04/32] elx: libefc_sli: queue create/destroy/parse routines James Smart
2020-01-08 7:45 ` Hannes Reinecke
2020-01-09 1:04 ` James Smart
2019-12-20 22:36 ` [PATCH v2 05/32] elx: libefc_sli: Populate and post different WQEs James Smart
2020-01-08 7:54 ` Hannes Reinecke
2020-01-09 1:04 ` James Smart
2019-12-20 22:36 ` [PATCH v2 06/32] elx: libefc_sli: bmbx routines and SLI config commands James Smart
2020-01-08 8:05 ` Hannes Reinecke
2019-12-20 22:36 ` [PATCH v2 07/32] elx: libefc_sli: APIs to setup SLI library James Smart
2020-01-08 8:22 ` Hannes Reinecke
2020-01-09 1:29 ` James Smart
2019-12-20 22:36 ` [PATCH v2 08/32] elx: libefc: Generic state machine framework James Smart
2020-01-09 7:05 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 09/32] elx: libefc: Emulex FC discovery library APIs and definitions James Smart
2020-01-09 7:16 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 10/32] elx: libefc: FC Domain state machine interfaces James Smart
2020-01-09 7:27 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 11/32] elx: libefc: SLI and FC PORT " James Smart
2020-01-09 7:34 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 12/32] elx: libefc: Remote node " James Smart
2020-01-09 8:31 ` Hannes Reinecke
2020-01-09 9:57 ` Daniel Wagner
2019-12-20 22:37 ` [PATCH v2 13/32] elx: libefc: Fabric " James Smart
2020-01-09 8:34 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 14/32] elx: libefc: FC node ELS and state handling James Smart
2020-01-09 8:39 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 15/32] elx: efct: Data structures and defines for hw operations James Smart
2020-01-09 8:41 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 16/32] elx: efct: Driver initialization routines James Smart
2020-01-09 9:01 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 17/32] elx: efct: Hardware queues creation and deletion James Smart
2020-01-09 9:10 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 18/32] elx: efct: RQ buffer, memory pool allocation and deallocation APIs James Smart
2020-01-09 9:13 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 19/32] elx: efct: Hardware IO and SGL initialization James Smart
2020-01-09 9:22 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 20/32] elx: efct: Hardware queues processing James Smart
2020-01-09 9:24 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 21/32] elx: efct: Unsolicited FC frame processing routines James Smart
2020-01-09 9:26 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 22/32] elx: efct: Extended link Service IO handling James Smart
2020-01-09 9:38 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 23/32] elx: efct: SCSI IO handling routines James Smart
2020-01-09 9:41 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 24/32] elx: efct: LIO backend interface routines James Smart
2020-01-09 3:56 ` Bart Van Assche [this message]
2019-12-20 22:37 ` [PATCH v2 25/32] elx: efct: Hardware IO submission routines James Smart
2020-01-09 9:52 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 26/32] elx: efct: link statistics and SFP data James Smart
2020-01-09 10:12 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 27/32] elx: efct: xport and hardware teardown routines James Smart
2020-01-09 10:14 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 28/32] elx: efct: IO timeout handling routines James Smart
2020-01-09 11:27 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 29/32] elx: efct: Firmware update, async link processing James Smart
2020-01-09 11:45 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 30/32] elx: efct: scsi_transport_fc host interface support James Smart
2020-01-09 11:46 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 31/32] elx: efct: Add Makefile and Kconfig for efct driver James Smart
2019-12-20 23:17 ` Randy Dunlap
2020-01-09 11:47 ` Hannes Reinecke
2019-12-20 22:37 ` [PATCH v2 32/32] elx: efct: Tie into kernel Kconfig and build process James Smart
2019-12-24 7:45 ` kbuild test robot
2019-12-24 21:01 ` Nathan Chancellor
2019-12-25 16:09 ` James Smart
2020-01-09 11:47 ` Hannes Reinecke
2019-12-29 18:27 ` [PATCH v2 00/32] [NEW] efct: Broadcom (Emulex) FC Target driver Sebastian Herbszt
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=a1c547a3-f5b8-54bc-b9e9-5b0ad0786ed3@acm.org \
--to=bvanassche@acm.org \
--cc=dwagner@suse.de \
--cc=jsmart2021@gmail.com \
--cc=linux-scsi@vger.kernel.org \
--cc=maier@linux.ibm.com \
--cc=ram.vegesna@broadcom.com \
/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;
as well as URLs for NNTP newsgroup(s).