[PATCH v3 7/7] nvme-fabrics: Add FC LLDD loopback driver to test FC-NVME
J Freyensee
james_p_freyensee at linux.intel.com
Wed Oct 26 13:00:29 PDT 2016
> +static struct fcloop_nport *
> +fcloop_alloc_nport(const char *buf, size_t count, bool remoteport)
> +{
> + struct fcloop_nport *newnport, *nport = NULL;
> + struct fcloop_lport *tmplport, *lport = NULL;
> + struct fcloop_ctrl_options *opts;
> + unsigned long flags;
> + u32 opts_mask = (remoteport) ? RPORT_OPTS : TGTPORT_OPTS;
> + int ret;
> +
> + opts = kzalloc(sizeof(*opts), GFP_KERNEL);
> + if (!opts)
> + return NULL;
> +
> + ret = fcloop_parse_options(opts, buf);
> + if (ret)
> + goto out_free_opts;
> +
> + /* everything there ? */
> + if ((opts->mask & opts_mask) != opts_mask) {
> + ret = -EINVAL;
> + goto out_free_opts;
> + }
> +
> + newnport = kzalloc(sizeof(*nport), GFP_KERNEL);
Nitpick- looks odd to use a pointer variable instead of *newnport for
the sizeof parameter, especially when that is the way '*opts' is done a
few lines above it.
> + if (!newnport)
> + goto out_free_opts;
> +
> + INIT_LIST_HEAD(&newnport->nport_list);
> + newnport->node_name = opts->wwnn;
> + newnport->port_name = opts->wwpn;
> + if (opts->mask & NVMF_OPT_ROLES)
> + newnport->port_role = opts->roles;
> + if (opts->mask & NVMF_OPT_FCADDR)
> + newnport->port_id = opts->fcaddr;
> + kref_init(&newnport->ref);
> +
> + spin_lock_irqsave(&fcloop_lock, flags);
> +
> + list_for_each_entry(tmplport, &fcloop_lports, lport_list) {
> + if ((tmplport->localport->node_name == opts->wwnn)
> &&
> + (tmplport->localport->port_name == opts->wwpn))
> + goto out_invalid_opts;
> +
> + if ((tmplport->localport->node_name == opts->lpwwnn)
> &&
> + (tmplport->localport->port_name == opts-
> >lpwwpn))
> + lport = tmplport;
> + }
> +
> + if (remoteport) {
> + if (!lport)
> + goto out_invalid_opts;
> + newnport->lport = lport;
> + }
> +
> + list_for_each_entry(nport, &fcloop_nports, nport_list) {
> + if (nport->node_name == opts->wwnn &&
> + nport->port_name == opts->wwpn) {
> + if ((remoteport && nport->rport) ||
> + (!remoteport && nport->tport)) {
> + nport = NULL;
> + goto out_invalid_opts;
> + }
> +
> + fcloop_nport_get(nport);
> +
> + spin_unlock_irqrestore(&fcloop_lock, flags);
> +
> + if (remoteport)
> + nport->lport = lport;
> + if (opts->mask & NVMF_OPT_ROLES)
> + nport->port_role = opts->roles;
> + if (opts->mask & NVMF_OPT_FCADDR)
> + nport->port_id = opts->fcaddr;
> + goto out_free_opts;
It looks like if we ever get here, we will leak memory as newnport has
been kzalloc'ed at this point but this will jump to the "out_free_opts"
goto statement.
> + }
> + }
> +
> + list_add_tail(&newnport->nport_list, &fcloop_nports);
> +
> + spin_unlock_irqrestore(&fcloop_lock, flags);
> +
> + kfree(opts);
> + return newnport;
> +
> +out_invalid_opts:
> + spin_unlock_irqrestore(&fcloop_lock, flags);
> + kfree(newnport);
> +out_free_opts:
> + kfree(opts);
> + return nport;
> +}
> +
> +static ssize_t
> +fcloop_create_remote_port(struct device *dev, struct
> device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct nvme_fc_remote_port *remoteport;
> + struct fcloop_nport *nport;
> + struct fcloop_rport *rport;
> + struct nvme_fc_port_info pinfo;
> + int ret;
> +
> + nport = fcloop_alloc_nport(buf, count, true);
> + if (!nport)
> + return -EIO;
> +
> + pinfo.node_name = nport->node_name;
> + pinfo.port_name = nport->port_name;
> + pinfo.port_role = nport->port_role;
> + pinfo.port_id = nport->port_id;
> +
> + ret = nvme_fc_register_remoteport(nport->lport->localport,
> + &pinfo,
> &remoteport);
> + if (ret || !remoteport) {
> + fcloop_nport_put(nport);
> + return ret;
Possible memory leak for nport??
> + }
> +
> + /* success */
> + rport = remoteport->private;
> + rport->remoteport = remoteport;
> + rport->targetport = (nport->tport) ? nport->tport-
> >targetport : NULL;
> + if (nport->tport) {
> + nport->tport->remoteport = remoteport;
> + nport->tport->lport = nport->lport;
> + }
> + rport->nport = nport;
> + rport->lport = nport->lport;
> + nport->rport = rport;
> +
> + return ret ? ret : count;
> +}
> +
> +
snip...
> +
> +static ssize_t
> +fcloop_create_target_port(struct device *dev, struct
> device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct nvmet_fc_target_port *targetport;
> + struct fcloop_nport *nport;
> + struct fcloop_tport *tport;
> + struct nvmet_fc_port_info tinfo;
> + int ret;
> +
> + nport = fcloop_alloc_nport(buf, count, false);
> + if (!nport)
> + return -EIO;
> +
> + tinfo.node_name = nport->node_name;
> + tinfo.port_name = nport->port_name;
> + tinfo.port_id = nport->port_id;
> +
> + ret = nvmet_fc_register_targetport(&tinfo, &tgttemplate,
> NULL,
> + &targetport);
> + if (ret) {
> + fcloop_nport_put(nport);
> + return ret;
Possible memory leak by not de-allocating 'nport'?
> + }
> +
> + /* success */
> + tport = targetport->private;
> + tport->targetport = targetport;
> + tport->remoteport = (nport->rport) ? nport->rport-
> >remoteport : NULL;
> + if (nport->rport)
> + nport->rport->targetport = targetport;
> + tport->nport = nport;
> + tport->lport = nport->lport;
> + nport->tport = tport;
> +
> + return ret ? ret : count;
> +}
> +
>
Thanks,
J
More information about the Linux-nvme
mailing list