]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - src/patches/suse-2.6.27.31/patches.drivers/libfc-check-for-err-when-recv-state-is-incorrect.diff
Added missing Xen Kernel Patches which were not commited because
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.drivers / libfc-check-for-err-when-recv-state-is-incorrect.diff
diff --git a/src/patches/suse-2.6.27.31/patches.drivers/libfc-check-for-err-when-recv-state-is-incorrect.diff b/src/patches/suse-2.6.27.31/patches.drivers/libfc-check-for-err-when-recv-state-is-incorrect.diff
new file mode 100644 (file)
index 0000000..9a2b00f
--- /dev/null
@@ -0,0 +1,218 @@
+From 251b8184b1bd4e17656d72ba9cffcba733092064 Mon Sep 17 00:00:00 2001
+From: Robert Love <robert.w.love@intel.com>
+Date: Mon, 2 Feb 2009 10:13:06 -0800
+Subject: [PATCH] libfc: check for err when recv and state is incorrect
+References: bnc#473602
+
+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: Hannes Reinecke <hare@suse.de>
+
+---
+ drivers/scsi/libfc/fc_lport.c |   50 +++++++++++++++++++++---------------------
+ drivers/scsi/libfc/fc_rport.c |   30 ++++++++++++-------------
+ 2 files changed, 40 insertions(+), 40 deletions(-)
+
+--- 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_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));
+@@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct 
+       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 &&
+@@ -1133,17 +1133,17 @@ static void fc_lport_scr_resp(struct fc_
+       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);
+@@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc
+       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);
+@@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct f
+       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) {
+--- 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 f
+       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) {
+@@ -614,17 +614,17 @@ static void fc_rport_prli_resp(struct fc
+       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));
+@@ -764,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_
+       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;