Bladeren bron

scsi: libfc: sanitize E_D_TOV and R_A_TOV setting

When setting the FCP timeout we need to ensure a lower boundary
for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
issues due to the fcp timer firing too early.

Signed-off-by: Hannes Reinecke <hare@suse.com>
Acked-by: Johannes Thumshirn <jth@kernel.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Hannes Reinecke 8 jaren geleden
bovenliggende
commit
76e72ad117
3 gewijzigde bestanden met toevoegingen van 14 en 9 verwijderingen
  1. 5 4
      drivers/scsi/libfc/fc_fcp.c
  2. 5 3
      drivers/scsi/libfc/fc_lport.c
  3. 4 2
      drivers/scsi/libfc/fc_rport.c

+ 5 - 4
drivers/scsi/libfc/fc_fcp.c

@@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
 static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
 static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
 {
 {
 	struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
 	struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
+	unsigned int e_d_tov = FC_DEF_E_D_TOV;
 
 
-	return msecs_to_jiffies(rpriv->e_d_tov) + HZ;
+	if (rpriv && rpriv->e_d_tov > e_d_tov)
+		e_d_tov = rpriv->e_d_tov;
+	return msecs_to_jiffies(e_d_tov) + HZ;
 }
 }
 
 
 /**
 /**
@@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
 	struct fc_seq *seq;
 	struct fc_seq *seq;
 	struct fcp_srr *srr;
 	struct fcp_srr *srr;
 	struct fc_frame *fp;
 	struct fc_frame *fp;
-	unsigned int rec_tov;
 
 
 	rport = fsp->rport;
 	rport = fsp->rport;
 	rpriv = rport->dd_data;
 	rpriv = rport->dd_data;
@@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
 		       rpriv->local_port->port_id, FC_TYPE_FCP,
 		       rpriv->local_port->port_id, FC_TYPE_FCP,
 		       FC_FCTL_REQ, 0);
 		       FC_FCTL_REQ, 0);
 
 
-	rec_tov = get_fsp_rec_tov(fsp);
 	seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
 	seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
 				      fc_fcp_pkt_destroy,
 				      fc_fcp_pkt_destroy,
-				      fsp, jiffies_to_msecs(rec_tov));
+				      fsp, get_fsp_rec_tov(fsp));
 	if (!seq)
 	if (!seq)
 		goto retry;
 		goto retry;
 
 

+ 5 - 3
drivers/scsi/libfc/fc_lport.c

@@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 	if ((csp_flags & FC_SP_FT_FPORT) == 0) {
 	if ((csp_flags & FC_SP_FT_FPORT) == 0) {
 		if (e_d_tov > lport->e_d_tov)
 		if (e_d_tov > lport->e_d_tov)
 			lport->e_d_tov = e_d_tov;
 			lport->e_d_tov = e_d_tov;
-		lport->r_a_tov = 2 * e_d_tov;
+		lport->r_a_tov = 2 * lport->e_d_tov;
 		fc_lport_set_port_id(lport, did, fp);
 		fc_lport_set_port_id(lport, did, fp);
 		printk(KERN_INFO "host%d: libfc: "
 		printk(KERN_INFO "host%d: libfc: "
 		       "Port (%6.6x) entered "
 		       "Port (%6.6x) entered "
@@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
 				   get_unaligned_be64(
 				   get_unaligned_be64(
 					   &flp->fl_wwnn));
 					   &flp->fl_wwnn));
 	} else {
 	} else {
-		lport->e_d_tov = e_d_tov;
-		lport->r_a_tov = r_a_tov;
+		if (e_d_tov > lport->e_d_tov)
+			lport->e_d_tov = e_d_tov;
+		if (r_a_tov > lport->r_a_tov)
+			lport->r_a_tov = r_a_tov;
 		fc_host_fabric_name(lport->host) =
 		fc_host_fabric_name(lport->host) =
 			get_unaligned_be64(&flp->fl_wwnn);
 			get_unaligned_be64(&flp->fl_wwnn);
 		fc_lport_set_port_id(lport, did, fp);
 		fc_lport_set_port_id(lport, did, fp);

+ 4 - 2
drivers/scsi/libfc/fc_rport.c

@@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
 			tov = ntohl(rtv->rtv_r_a_tov);
 			tov = ntohl(rtv->rtv_r_a_tov);
 			if (tov == 0)
 			if (tov == 0)
 				tov = 1;
 				tov = 1;
-			rdata->r_a_tov = tov;
+			if (tov > rdata->r_a_tov)
+				rdata->r_a_tov = tov;
 			tov = ntohl(rtv->rtv_e_d_tov);
 			tov = ntohl(rtv->rtv_e_d_tov);
 			if (toq & FC_ELS_RTV_EDRES)
 			if (toq & FC_ELS_RTV_EDRES)
 				tov /= 1000000;
 				tov /= 1000000;
 			if (tov == 0)
 			if (tov == 0)
 				tov = 1;
 				tov = 1;
-			rdata->e_d_tov = tov;
+			if (tov > rdata->e_d_tov)
+				rdata->e_d_tov = tov;
 		}
 		}
 	}
 	}