[Open-FCoE] [RFC PATCH 5/5] libfc: check for err when recv and state is incorrect

Ma, Steve steve.ma at intel.com
Fri Jan 30 19:10:00 UTC 2009


This patch fixes the null-pointer Oops problem of toggling DCB PFC enable bit while FCoE traffic is in progress. -Steve

>-----Original Message-----
>From: devel-bounces at open-fcoe.org [mailto:devel-bounces at open-fcoe.org] On
>Behalf Of Robert Love
>Sent: Wednesday, January 28, 2009 12:49 PM
>To: devel at open-fcoe.org
>Subject: [Open-FCoE] [RFC PATCH 5/5] 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 and then 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 at intel.com>
>---
>
> drivers/scsi/libfc/fc_lport.c |   50 +++++++++++++++++++++----------------
>----
> 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 5bc8511..b28397e 100644
>--- a/drivers/scsi/libfc/fc_lport.c
>+++ b/drivers/scsi/libfc/fc_lport.c
>@@ -1029,17 +1029,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));
>
>@@ -1081,17 +1081,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 &&
>@@ -1131,17 +1131,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);
>@@ -1357,17 +1357,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);
>@@ -1441,17 +1441,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) {
>diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
>index 13dd606..d707ab1 100644
>--- a/drivers/scsi/libfc/fc_rport.c
>+++ b/drivers/scsi/libfc/fc_rport.c
>@@ -526,17 +526,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) {
>@@ -640,17 +640,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));
>@@ -797,17 +797,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;
>
>_______________________________________________
>devel mailing list
>devel at open-fcoe.org
>http://www.open-fcoe.org/mailman/listinfo/devel



More information about the devel mailing list