Commit efaf5c08 authored by Robert Love's avatar Robert Love Committed by James Bottomley

[SCSI] libfc: check for err when recv and state is incorrect

If we've just created an interface and the an rport is
logging in we may have a request on the wire (say PRLI).
If we destroy the interface, we'll go through each rport
on the disc->rports list and set each rport's state to NONE.
Then the lport will reset the EM. The EM reset will send a
CLOSED event to the prli_resp() handler which will notice
that the state != PRLI. In this case it frees the frame
pointer, decrements the refcount and unlocks the rport.

The problem is that there isn't a frame in this case. It's
just a pointer with an embedded error code. The free causes
an Oops.

This patch moves the error checking to be before the state
checking.
Signed-off-by: default avatarRobert Love <robert.w.love@intel.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent d3b33327
...@@ -1031,17 +1031,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1031,17 +1031,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RFT_ID response\n"); FC_DEBUG_LPORT("Received a RFT_ID response\n");
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
if (lport->state != LPORT_ST_RFT_ID) { if (lport->state != LPORT_ST_RFT_ID) {
FC_DBG("Received a RFT_ID response, but in state %s\n", FC_DBG("Received a RFT_ID response, but in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
fh = fc_frame_header_get(fp); fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct)); ct = fc_frame_payload_get(fp, sizeof(*ct));
...@@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RPN_ID response\n"); FC_DEBUG_LPORT("Received a RPN_ID response\n");
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
if (lport->state != LPORT_ST_RPN_ID) { if (lport->state != LPORT_ST_RPN_ID) {
FC_DBG("Received a RPN_ID response, but in state %s\n", FC_DBG("Received a RPN_ID response, but in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
fh = fc_frame_header_get(fp); fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct)); ct = fc_frame_payload_get(fp, sizeof(*ct));
if (fh && ct && fh->fh_type == FC_TYPE_CT && if (fh && ct && fh->fh_type == FC_TYPE_CT &&
...@@ -1133,17 +1133,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1133,17 +1133,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a SCR response\n"); FC_DEBUG_LPORT("Received a SCR response\n");
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
if (lport->state != LPORT_ST_SCR) { if (lport->state != LPORT_ST_SCR) {
FC_DBG("Received a SCR response, but in state %s\n", FC_DBG("Received a SCR response, but in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
op = fc_frame_payload_op(fp); op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) if (op == ELS_LS_ACC)
fc_lport_enter_ready(lport); fc_lport_enter_ready(lport);
...@@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a LOGO response\n"); FC_DEBUG_LPORT("Received a LOGO response\n");
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
if (lport->state != LPORT_ST_LOGO) { if (lport->state != LPORT_ST_LOGO) {
FC_DBG("Received a LOGO response, but in state %s\n", FC_DBG("Received a LOGO response, but in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
op = fc_frame_payload_op(fp); op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) if (op == ELS_LS_ACC)
fc_lport_enter_reset(lport); fc_lport_enter_reset(lport);
...@@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a FLOGI response\n"); FC_DEBUG_LPORT("Received a FLOGI response\n");
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
if (lport->state != LPORT_ST_FLOGI) { if (lport->state != LPORT_ST_FLOGI) {
FC_DBG("Received a FLOGI response, but in state %s\n", FC_DBG("Received a FLOGI response, but in state %s\n",
fc_lport_state(lport)); fc_lport_state(lport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}
fh = fc_frame_header_get(fp); fh = fc_frame_header_get(fp);
did = ntoh24(fh->fh_d_id); did = ntoh24(fh->fh_d_id);
if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
......
...@@ -505,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -505,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n",
rport->port_id); rport->port_id);
if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}
if (rdata->rp_state != RPORT_ST_PLOGI) { if (rdata->rp_state != RPORT_ST_PLOGI) {
FC_DBG("Received a PLOGI response, but in state %s\n", FC_DBG("Received a PLOGI response, but in state %s\n",
fc_rport_state(rport)); fc_rport_state(rport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}
op = fc_frame_payload_op(fp); op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC && if (op == ELS_LS_ACC &&
(plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
...@@ -614,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -614,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n",
rport->port_id); rport->port_id);
if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}
if (rdata->rp_state != RPORT_ST_PRLI) { if (rdata->rp_state != RPORT_ST_PRLI) {
FC_DBG("Received a PRLI response, but in state %s\n", FC_DBG("Received a PRLI response, but in state %s\n",
fc_rport_state(rport)); fc_rport_state(rport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}
op = fc_frame_payload_op(fp); op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) { if (op == ELS_LS_ACC) {
pp = fc_frame_payload_get(fp, sizeof(*pp)); pp = fc_frame_payload_get(fp, sizeof(*pp));
...@@ -764,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -764,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n",
rport->port_id); rport->port_id);
if (IS_ERR(fp)) {
fc_rport_error(rport, fp);
goto err;
}
if (rdata->rp_state != RPORT_ST_RTV) { if (rdata->rp_state != RPORT_ST_RTV) {
FC_DBG("Received a RTV response, but in state %s\n", FC_DBG("Received a RTV response, but in state %s\n",
fc_rport_state(rport)); fc_rport_state(rport));
goto out; goto out;
} }
if (IS_ERR(fp)) {
fc_rport_error(rport, fp);
goto err;
}
op = fc_frame_payload_op(fp); op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) { if (op == ELS_LS_ACC) {
struct fc_els_rtv_acc *rtv; struct fc_els_rtv_acc *rtv;
......
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