Skip to content

Commit

Permalink
[SCSI] libfc: check for err when recv and state is incorrect
Browse files Browse the repository at this point in the history
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: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Robert Love authored and James Bottomley committed Mar 6, 2009
1 parent d3b3332 commit efaf5c0
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 40 deletions.
50 changes: 25 additions & 25 deletions drivers/scsi/libfc/fc_lport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

if (lport->state != LPORT_ST_RFT_ID) {
FC_DBG("Received a RFT_ID response, but in state %s\n",
fc_lport_state(lport));
goto out;
}

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));

Expand Down Expand Up @@ -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");

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

if (lport->state != LPORT_ST_RPN_ID) {
FC_DBG("Received a RPN_ID response, but in state %s\n",
fc_lport_state(lport));
goto out;
}

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
if (fh && ct && fh->fh_type == FC_TYPE_CT &&
Expand Down Expand Up @@ -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");

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

if (lport->state != LPORT_ST_SCR) {
FC_DBG("Received a SCR response, but in state %s\n",
fc_lport_state(lport));
goto out;
}

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_ready(lport);
Expand Down Expand Up @@ -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");

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

if (lport->state != LPORT_ST_LOGO) {
FC_DBG("Received a LOGO response, but in state %s\n",
fc_lport_state(lport));
goto out;
}

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_reset(lport);
Expand Down Expand Up @@ -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");

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

if (lport->state != LPORT_ST_FLOGI) {
FC_DBG("Received a FLOGI response, but in state %s\n",
fc_lport_state(lport));
goto out;
}

if (IS_ERR(fp)) {
fc_lport_error(lport, fp);
goto err;
}

fh = fc_frame_header_get(fp);
did = ntoh24(fh->fh_d_id);
if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
Expand Down
30 changes: 15 additions & 15 deletions drivers/scsi/libfc/fc_rport.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
rport->port_id);

if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}

if (rdata->rp_state != RPORT_ST_PLOGI) {
FC_DBG("Received a PLOGI response, but in state %s\n",
fc_rport_state(rport));
goto out;
}

if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}

op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC &&
(plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
Expand Down Expand Up @@ -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",
rport->port_id);

if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}

if (rdata->rp_state != RPORT_ST_PRLI) {
FC_DBG("Received a PRLI response, but in state %s\n",
fc_rport_state(rport));
goto out;
}

if (IS_ERR(fp)) {
fc_rport_error_retry(rport, fp);
goto err;
}

op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
pp = fc_frame_payload_get(fp, sizeof(*pp));
Expand Down Expand Up @@ -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",
rport->port_id);

if (IS_ERR(fp)) {
fc_rport_error(rport, fp);
goto err;
}

if (rdata->rp_state != RPORT_ST_RTV) {
FC_DBG("Received a RTV response, but in state %s\n",
fc_rport_state(rport));
goto out;
}

if (IS_ERR(fp)) {
fc_rport_error(rport, fp);
goto err;
}

op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
struct fc_els_rtv_acc *rtv;
Expand Down

0 comments on commit efaf5c0

Please sign in to comment.