Commit 56efc304 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: qedf: fc_rport_priv reference counting fixes

The fc_rport_priv structure is reference counted, so we need to ensure that
the reference is increased before accessing the structure.
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarSaurav Kashyap <skashyap@marvell.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6f15d0c0
...@@ -378,12 +378,18 @@ void qedf_restart_rport(struct qedf_rport *fcport) ...@@ -378,12 +378,18 @@ void qedf_restart_rport(struct qedf_rport *fcport)
spin_unlock_irqrestore(&fcport->rport_lock, flags); spin_unlock_irqrestore(&fcport->rport_lock, flags);
rdata = fcport->rdata; rdata = fcport->rdata;
if (rdata) { if (rdata && !kref_get_unless_zero(&rdata->kref)) {
fcport->rdata = NULL;
rdata = NULL;
}
if (rdata && rdata->rp_state == RPORT_ST_READY) {
lport = fcport->qedf->lport; lport = fcport->qedf->lport;
port_id = rdata->ids.port_id; port_id = rdata->ids.port_id;
QEDF_ERR(&(fcport->qedf->dbg_ctx), QEDF_ERR(&(fcport->qedf->dbg_ctx),
"LOGO port_id=%x.\n", port_id); "LOGO port_id=%x.\n", port_id);
fc_rport_logoff(rdata); fc_rport_logoff(rdata);
kref_put(&rdata->kref, fc_rport_destroy);
mutex_lock(&lport->disc.disc_mutex); mutex_lock(&lport->disc.disc_mutex);
/* Recreate the rport and log back in */ /* Recreate the rport and log back in */
rdata = fc_rport_create(lport, port_id); rdata = fc_rport_create(lport, port_id);
...@@ -393,6 +399,7 @@ void qedf_restart_rport(struct qedf_rport *fcport) ...@@ -393,6 +399,7 @@ void qedf_restart_rport(struct qedf_rport *fcport)
fcport->rdata = rdata; fcport->rdata = rdata;
} else { } else {
mutex_unlock(&lport->disc.disc_mutex); mutex_unlock(&lport->disc.disc_mutex);
fcport->rdata = NULL;
} }
} }
clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags); clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags);
......
...@@ -1799,6 +1799,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) ...@@ -1799,6 +1799,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
goto out; goto out;
} }
qedf = fcport->qedf;
rdata = fcport->rdata; rdata = fcport->rdata;
if (!rdata || !kref_get_unless_zero(&rdata->kref)) { if (!rdata || !kref_get_unless_zero(&rdata->kref)) {
...@@ -1808,32 +1809,31 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) ...@@ -1808,32 +1809,31 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
} }
r_a_tov = rdata->r_a_tov; r_a_tov = rdata->r_a_tov;
qedf = fcport->qedf;
lport = qedf->lport; lport = qedf->lport;
if (lport->state != LPORT_ST_READY || !(lport->link_up)) { if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
QEDF_ERR(&(qedf->dbg_ctx), "link is not ready\n"); QEDF_ERR(&(qedf->dbg_ctx), "link is not ready\n");
rc = 1; rc = 1;
goto out; goto drop_rdata_kref;
} }
if (atomic_read(&qedf->link_down_tmo_valid) > 0) { if (atomic_read(&qedf->link_down_tmo_valid) > 0) {
QEDF_ERR(&(qedf->dbg_ctx), "link_down_tmo active.\n"); QEDF_ERR(&(qedf->dbg_ctx), "link_down_tmo active.\n");
rc = 1; rc = 1;
goto out; goto drop_rdata_kref;
} }
/* Ensure room on SQ */ /* Ensure room on SQ */
if (!atomic_read(&fcport->free_sqes)) { if (!atomic_read(&fcport->free_sqes)) {
QEDF_ERR(&(qedf->dbg_ctx), "No SQ entries available\n"); QEDF_ERR(&(qedf->dbg_ctx), "No SQ entries available\n");
rc = 1; rc = 1;
goto out; goto drop_rdata_kref;
} }
if (test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) { if (test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) {
QEDF_ERR(&qedf->dbg_ctx, "fcport is uploading.\n"); QEDF_ERR(&qedf->dbg_ctx, "fcport is uploading.\n");
rc = 1; rc = 1;
goto out; goto drop_rdata_kref;
} }
if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) || if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
...@@ -1843,7 +1843,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) ...@@ -1843,7 +1843,7 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
"cleanup or abort processing or already " "cleanup or abort processing or already "
"completed.\n", io_req->xid); "completed.\n", io_req->xid);
rc = 1; rc = 1;
goto out; goto drop_rdata_kref;
} }
kref_get(&io_req->refcount); kref_get(&io_req->refcount);
...@@ -1876,6 +1876,8 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts) ...@@ -1876,6 +1876,8 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
spin_unlock_irqrestore(&fcport->rport_lock, flags); spin_unlock_irqrestore(&fcport->rport_lock, flags);
drop_rdata_kref:
kref_put(&rdata->kref, fc_rport_destroy);
out: out:
return rc; return rc;
} }
...@@ -2217,6 +2219,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd, ...@@ -2217,6 +2219,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
unsigned long flags; unsigned long flags;
struct fcoe_wqe *sqe; struct fcoe_wqe *sqe;
u16 sqe_idx; u16 sqe_idx;
struct fc_rport_priv *rdata = fcport->rdata;
if (!sc_cmd) { if (!sc_cmd) {
QEDF_ERR(&(qedf->dbg_ctx), "invalid arg\n"); QEDF_ERR(&(qedf->dbg_ctx), "invalid arg\n");
...@@ -2230,8 +2233,13 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd, ...@@ -2230,8 +2233,13 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
return FAILED; return FAILED;
} }
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_SCSI_TM, "portid = 0x%x " if (!rdata || !kref_get_unless_zero(&rdata->kref)) {
"tm_flags = %d\n", fcport->rdata->ids.port_id, tm_flags); QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_SCSI_TM, "stale rport\n");
return FAILED;
}
QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_SCSI_TM,
"portid = 0x%x tm_flags = %d\n",
rdata->ids.port_id, tm_flags);
io_req = qedf_alloc_cmd(fcport, QEDF_TASK_MGMT_CMD); io_req = qedf_alloc_cmd(fcport, QEDF_TASK_MGMT_CMD);
if (!io_req) { if (!io_req) {
...@@ -2327,6 +2335,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd, ...@@ -2327,6 +2335,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, struct scsi_cmnd *sc_cmd,
rc = SUCCESS; rc = SUCCESS;
} }
reset_tmf_err: reset_tmf_err:
kref_put(&rdata->kref, fc_rport_destroy);
return rc; return rc;
} }
......
...@@ -1334,6 +1334,8 @@ static void qedf_upload_connection(struct qedf_ctx *qedf, ...@@ -1334,6 +1334,8 @@ static void qedf_upload_connection(struct qedf_ctx *qedf,
static void qedf_cleanup_fcport(struct qedf_ctx *qedf, static void qedf_cleanup_fcport(struct qedf_ctx *qedf,
struct qedf_rport *fcport) struct qedf_rport *fcport)
{ {
struct fc_rport_priv *rdata = fcport->rdata;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_CONN, "Cleaning up portid=%06x.\n", QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_CONN, "Cleaning up portid=%06x.\n",
fcport->rdata->ids.port_id); fcport->rdata->ids.port_id);
...@@ -1345,6 +1347,7 @@ static void qedf_cleanup_fcport(struct qedf_ctx *qedf, ...@@ -1345,6 +1347,7 @@ static void qedf_cleanup_fcport(struct qedf_ctx *qedf,
qedf_free_sq(qedf, fcport); qedf_free_sq(qedf, fcport);
fcport->rdata = NULL; fcport->rdata = NULL;
fcport->qedf = NULL; fcport->qedf = NULL;
kref_put(&rdata->kref, fc_rport_destroy);
} }
/** /**
...@@ -1420,6 +1423,8 @@ static void qedf_rport_event_handler(struct fc_lport *lport, ...@@ -1420,6 +1423,8 @@ static void qedf_rport_event_handler(struct fc_lport *lport,
break; break;
} }
/* Initial reference held on entry, so this can't fail */
kref_get(&rdata->kref);
fcport->rdata = rdata; fcport->rdata = rdata;
fcport->rport = rport; fcport->rport = rport;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment