aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorRobert Love <robert.w.love@intel.com>2009-02-27 13:55:34 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-06 16:44:36 -0500
commitefaf5c085dd2d31757b0ff7886970dfddd8d1808 (patch)
treec88ab287ed1b78ecad88370c1c8929f17f13c271 /drivers/scsi
parentd3b33327cab0c8e9cae2c12d908ca79433c0d1ac (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')
-rw-r--r--drivers/scsi/libfc/fc_lport.c50
-rw-r--r--drivers/scsi/libfc/fc_rport.c30
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;