diff options
author | Robert Love <robert.w.love@intel.com> | 2009-02-27 13:55:34 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-03-06 16:44:36 -0500 |
commit | efaf5c085dd2d31757b0ff7886970dfddd8d1808 (patch) | |
tree | c88ab287ed1b78ecad88370c1c8929f17f13c271 /drivers/scsi/libfc | |
parent | d3b33327cab0c8e9cae2c12d908ca79433c0d1ac (diff) |
[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: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 50 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 30 |
2 files changed, 40 insertions, 40 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 07335ae2947c..c00de2244c78 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -1031,17 +1031,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1031 | 1031 | ||
1032 | FC_DEBUG_LPORT("Received a RFT_ID response\n"); | 1032 | FC_DEBUG_LPORT("Received a RFT_ID response\n"); |
1033 | 1033 | ||
1034 | if (IS_ERR(fp)) { | ||
1035 | fc_lport_error(lport, fp); | ||
1036 | goto err; | ||
1037 | } | ||
1038 | |||
1034 | if (lport->state != LPORT_ST_RFT_ID) { | 1039 | if (lport->state != LPORT_ST_RFT_ID) { |
1035 | FC_DBG("Received a RFT_ID response, but in state %s\n", | 1040 | FC_DBG("Received a RFT_ID response, but in state %s\n", |
1036 | fc_lport_state(lport)); | 1041 | fc_lport_state(lport)); |
1037 | goto out; | 1042 | goto out; |
1038 | } | 1043 | } |
1039 | 1044 | ||
1040 | if (IS_ERR(fp)) { | ||
1041 | fc_lport_error(lport, fp); | ||
1042 | goto err; | ||
1043 | } | ||
1044 | |||
1045 | fh = fc_frame_header_get(fp); | 1045 | fh = fc_frame_header_get(fp); |
1046 | ct = fc_frame_payload_get(fp, sizeof(*ct)); | 1046 | ct = fc_frame_payload_get(fp, sizeof(*ct)); |
1047 | 1047 | ||
@@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1083 | 1083 | ||
1084 | FC_DEBUG_LPORT("Received a RPN_ID response\n"); | 1084 | FC_DEBUG_LPORT("Received a RPN_ID response\n"); |
1085 | 1085 | ||
1086 | if (IS_ERR(fp)) { | ||
1087 | fc_lport_error(lport, fp); | ||
1088 | goto err; | ||
1089 | } | ||
1090 | |||
1086 | if (lport->state != LPORT_ST_RPN_ID) { | 1091 | if (lport->state != LPORT_ST_RPN_ID) { |
1087 | FC_DBG("Received a RPN_ID response, but in state %s\n", | 1092 | FC_DBG("Received a RPN_ID response, but in state %s\n", |
1088 | fc_lport_state(lport)); | 1093 | fc_lport_state(lport)); |
1089 | goto out; | 1094 | goto out; |
1090 | } | 1095 | } |
1091 | 1096 | ||
1092 | if (IS_ERR(fp)) { | ||
1093 | fc_lport_error(lport, fp); | ||
1094 | goto err; | ||
1095 | } | ||
1096 | |||
1097 | fh = fc_frame_header_get(fp); | 1097 | fh = fc_frame_header_get(fp); |
1098 | ct = fc_frame_payload_get(fp, sizeof(*ct)); | 1098 | ct = fc_frame_payload_get(fp, sizeof(*ct)); |
1099 | if (fh && ct && fh->fh_type == FC_TYPE_CT && | 1099 | 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 | 1133 | ||
1134 | FC_DEBUG_LPORT("Received a SCR response\n"); | 1134 | FC_DEBUG_LPORT("Received a SCR response\n"); |
1135 | 1135 | ||
1136 | if (IS_ERR(fp)) { | ||
1137 | fc_lport_error(lport, fp); | ||
1138 | goto err; | ||
1139 | } | ||
1140 | |||
1136 | if (lport->state != LPORT_ST_SCR) { | 1141 | if (lport->state != LPORT_ST_SCR) { |
1137 | FC_DBG("Received a SCR response, but in state %s\n", | 1142 | FC_DBG("Received a SCR response, but in state %s\n", |
1138 | fc_lport_state(lport)); | 1143 | fc_lport_state(lport)); |
1139 | goto out; | 1144 | goto out; |
1140 | } | 1145 | } |
1141 | 1146 | ||
1142 | if (IS_ERR(fp)) { | ||
1143 | fc_lport_error(lport, fp); | ||
1144 | goto err; | ||
1145 | } | ||
1146 | |||
1147 | op = fc_frame_payload_op(fp); | 1147 | op = fc_frame_payload_op(fp); |
1148 | if (op == ELS_LS_ACC) | 1148 | if (op == ELS_LS_ACC) |
1149 | fc_lport_enter_ready(lport); | 1149 | fc_lport_enter_ready(lport); |
@@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1359 | 1359 | ||
1360 | FC_DEBUG_LPORT("Received a LOGO response\n"); | 1360 | FC_DEBUG_LPORT("Received a LOGO response\n"); |
1361 | 1361 | ||
1362 | if (IS_ERR(fp)) { | ||
1363 | fc_lport_error(lport, fp); | ||
1364 | goto err; | ||
1365 | } | ||
1366 | |||
1362 | if (lport->state != LPORT_ST_LOGO) { | 1367 | if (lport->state != LPORT_ST_LOGO) { |
1363 | FC_DBG("Received a LOGO response, but in state %s\n", | 1368 | FC_DBG("Received a LOGO response, but in state %s\n", |
1364 | fc_lport_state(lport)); | 1369 | fc_lport_state(lport)); |
1365 | goto out; | 1370 | goto out; |
1366 | } | 1371 | } |
1367 | 1372 | ||
1368 | if (IS_ERR(fp)) { | ||
1369 | fc_lport_error(lport, fp); | ||
1370 | goto err; | ||
1371 | } | ||
1372 | |||
1373 | op = fc_frame_payload_op(fp); | 1373 | op = fc_frame_payload_op(fp); |
1374 | if (op == ELS_LS_ACC) | 1374 | if (op == ELS_LS_ACC) |
1375 | fc_lport_enter_reset(lport); | 1375 | fc_lport_enter_reset(lport); |
@@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1443 | 1443 | ||
1444 | FC_DEBUG_LPORT("Received a FLOGI response\n"); | 1444 | FC_DEBUG_LPORT("Received a FLOGI response\n"); |
1445 | 1445 | ||
1446 | if (IS_ERR(fp)) { | ||
1447 | fc_lport_error(lport, fp); | ||
1448 | goto err; | ||
1449 | } | ||
1450 | |||
1446 | if (lport->state != LPORT_ST_FLOGI) { | 1451 | if (lport->state != LPORT_ST_FLOGI) { |
1447 | FC_DBG("Received a FLOGI response, but in state %s\n", | 1452 | FC_DBG("Received a FLOGI response, but in state %s\n", |
1448 | fc_lport_state(lport)); | 1453 | fc_lport_state(lport)); |
1449 | goto out; | 1454 | goto out; |
1450 | } | 1455 | } |
1451 | 1456 | ||
1452 | if (IS_ERR(fp)) { | ||
1453 | fc_lport_error(lport, fp); | ||
1454 | goto err; | ||
1455 | } | ||
1456 | |||
1457 | fh = fc_frame_header_get(fp); | 1457 | fh = fc_frame_header_get(fp); |
1458 | did = ntoh24(fh->fh_d_id); | 1458 | did = ntoh24(fh->fh_d_id); |
1459 | if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { | 1459 | if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { |
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 81b3ca188789..4f23a9bb15a1 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -505,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
505 | FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", | 505 | FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", |
506 | rport->port_id); | 506 | rport->port_id); |
507 | 507 | ||
508 | if (IS_ERR(fp)) { | ||
509 | fc_rport_error_retry(rport, fp); | ||
510 | goto err; | ||
511 | } | ||
512 | |||
508 | if (rdata->rp_state != RPORT_ST_PLOGI) { | 513 | if (rdata->rp_state != RPORT_ST_PLOGI) { |
509 | FC_DBG("Received a PLOGI response, but in state %s\n", | 514 | FC_DBG("Received a PLOGI response, but in state %s\n", |
510 | fc_rport_state(rport)); | 515 | fc_rport_state(rport)); |
511 | goto out; | 516 | goto out; |
512 | } | 517 | } |
513 | 518 | ||
514 | if (IS_ERR(fp)) { | ||
515 | fc_rport_error_retry(rport, fp); | ||
516 | goto err; | ||
517 | } | ||
518 | |||
519 | op = fc_frame_payload_op(fp); | 519 | op = fc_frame_payload_op(fp); |
520 | if (op == ELS_LS_ACC && | 520 | if (op == ELS_LS_ACC && |
521 | (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { | 521 | (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 | FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", | 614 | FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", |
615 | rport->port_id); | 615 | rport->port_id); |
616 | 616 | ||
617 | if (IS_ERR(fp)) { | ||
618 | fc_rport_error_retry(rport, fp); | ||
619 | goto err; | ||
620 | } | ||
621 | |||
617 | if (rdata->rp_state != RPORT_ST_PRLI) { | 622 | if (rdata->rp_state != RPORT_ST_PRLI) { |
618 | FC_DBG("Received a PRLI response, but in state %s\n", | 623 | FC_DBG("Received a PRLI response, but in state %s\n", |
619 | fc_rport_state(rport)); | 624 | fc_rport_state(rport)); |
620 | goto out; | 625 | goto out; |
621 | } | 626 | } |
622 | 627 | ||
623 | if (IS_ERR(fp)) { | ||
624 | fc_rport_error_retry(rport, fp); | ||
625 | goto err; | ||
626 | } | ||
627 | |||
628 | op = fc_frame_payload_op(fp); | 628 | op = fc_frame_payload_op(fp); |
629 | if (op == ELS_LS_ACC) { | 629 | if (op == ELS_LS_ACC) { |
630 | pp = fc_frame_payload_get(fp, sizeof(*pp)); | 630 | 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 | FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", | 764 | FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", |
765 | rport->port_id); | 765 | rport->port_id); |
766 | 766 | ||
767 | if (IS_ERR(fp)) { | ||
768 | fc_rport_error(rport, fp); | ||
769 | goto err; | ||
770 | } | ||
771 | |||
767 | if (rdata->rp_state != RPORT_ST_RTV) { | 772 | if (rdata->rp_state != RPORT_ST_RTV) { |
768 | FC_DBG("Received a RTV response, but in state %s\n", | 773 | FC_DBG("Received a RTV response, but in state %s\n", |
769 | fc_rport_state(rport)); | 774 | fc_rport_state(rport)); |
770 | goto out; | 775 | goto out; |
771 | } | 776 | } |
772 | 777 | ||
773 | if (IS_ERR(fp)) { | ||
774 | fc_rport_error(rport, fp); | ||
775 | goto err; | ||
776 | } | ||
777 | |||
778 | op = fc_frame_payload_op(fp); | 778 | op = fc_frame_payload_op(fp); |
779 | if (op == ELS_LS_ACC) { | 779 | if (op == ELS_LS_ACC) { |
780 | struct fc_els_rtv_acc *rtv; | 780 | struct fc_els_rtv_acc *rtv; |