|
@@ -204,6 +204,10 @@ struct fcloop_lport {
|
|
|
struct completion unreg_done;
|
|
|
};
|
|
|
|
|
|
+struct fcloop_lport_priv {
|
|
|
+ struct fcloop_lport *lport;
|
|
|
+};
|
|
|
+
|
|
|
struct fcloop_rport {
|
|
|
struct nvme_fc_remote_port *remoteport;
|
|
|
struct nvmet_fc_target_port *targetport;
|
|
@@ -659,7 +663,8 @@ fcloop_nport_get(struct fcloop_nport *nport)
|
|
|
static void
|
|
|
fcloop_localport_delete(struct nvme_fc_local_port *localport)
|
|
|
{
|
|
|
- struct fcloop_lport *lport = localport->private;
|
|
|
+ struct fcloop_lport_priv *lport_priv = localport->private;
|
|
|
+ struct fcloop_lport *lport = lport_priv->lport;
|
|
|
|
|
|
/* release any threads waiting for the unreg to complete */
|
|
|
complete(&lport->unreg_done);
|
|
@@ -699,7 +704,7 @@ static struct nvme_fc_port_template fctemplate = {
|
|
|
.max_dif_sgl_segments = FCLOOP_SGL_SEGS,
|
|
|
.dma_boundary = FCLOOP_DMABOUND_4G,
|
|
|
/* sizes of additional private data for data structures */
|
|
|
- .local_priv_sz = sizeof(struct fcloop_lport),
|
|
|
+ .local_priv_sz = sizeof(struct fcloop_lport_priv),
|
|
|
.remote_priv_sz = sizeof(struct fcloop_rport),
|
|
|
.lsrqst_priv_sz = sizeof(struct fcloop_lsreq),
|
|
|
.fcprqst_priv_sz = sizeof(struct fcloop_ini_fcpreq),
|
|
@@ -730,11 +735,17 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
|
|
|
struct fcloop_ctrl_options *opts;
|
|
|
struct nvme_fc_local_port *localport;
|
|
|
struct fcloop_lport *lport;
|
|
|
- int ret;
|
|
|
+ struct fcloop_lport_priv *lport_priv;
|
|
|
+ unsigned long flags;
|
|
|
+ int ret = -ENOMEM;
|
|
|
+
|
|
|
+ lport = kzalloc(sizeof(*lport), GFP_KERNEL);
|
|
|
+ if (!lport)
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
opts = kzalloc(sizeof(*opts), GFP_KERNEL);
|
|
|
if (!opts)
|
|
|
- return -ENOMEM;
|
|
|
+ goto out_free_lport;
|
|
|
|
|
|
ret = fcloop_parse_options(opts, buf);
|
|
|
if (ret)
|
|
@@ -754,23 +765,25 @@ fcloop_create_local_port(struct device *dev, struct device_attribute *attr,
|
|
|
|
|
|
ret = nvme_fc_register_localport(&pinfo, &fctemplate, NULL, &localport);
|
|
|
if (!ret) {
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
/* success */
|
|
|
- lport = localport->private;
|
|
|
+ lport_priv = localport->private;
|
|
|
+ lport_priv->lport = lport;
|
|
|
+
|
|
|
lport->localport = localport;
|
|
|
INIT_LIST_HEAD(&lport->lport_list);
|
|
|
|
|
|
spin_lock_irqsave(&fcloop_lock, flags);
|
|
|
list_add_tail(&lport->lport_list, &fcloop_lports);
|
|
|
spin_unlock_irqrestore(&fcloop_lock, flags);
|
|
|
-
|
|
|
- /* mark all of the input buffer consumed */
|
|
|
- ret = count;
|
|
|
}
|
|
|
|
|
|
out_free_opts:
|
|
|
kfree(opts);
|
|
|
+out_free_lport:
|
|
|
+ /* free only if we're going to fail */
|
|
|
+ if (ret)
|
|
|
+ kfree(lport);
|
|
|
+
|
|
|
return ret ? ret : count;
|
|
|
}
|
|
|
|
|
@@ -792,6 +805,8 @@ __wait_localport_unreg(struct fcloop_lport *lport)
|
|
|
|
|
|
wait_for_completion(&lport->unreg_done);
|
|
|
|
|
|
+ kfree(lport);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|