Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 15 Nov 2018 16:02:45 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r340453 - head/sys/cam
Message-ID:  <201811151602.wAFG2jjU041028@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Thu Nov 15 16:02:45 2018
New Revision: 340453
URL: https://svnweb.freebsd.org/changeset/base/340453

Log:
  Add cam_iosched_set_latfcn to set a latency callback for high latency.
  
  It's often useful to have a callback when an I/O takes more than a
  threshold amount of time. This adds the infrastructure for periph
  devices to register one.
  
  One use-case is as a debugging aide when you need a semi-realtime
  indication of an I/O outlier so you can trigger bus capture gear for
  vendor analysis.
  
  Sponsored by: Netflix, Inc

Modified:
  head/sys/cam/cam_iosched.c
  head/sys/cam/cam_iosched.h

Modified: head/sys/cam/cam_iosched.c
==============================================================================
--- head/sys/cam/cam_iosched.c	Thu Nov 15 16:02:34 2018	(r340452)
+++ head/sys/cam/cam_iosched.c	Thu Nov 15 16:02:45 2018	(r340453)
@@ -294,6 +294,9 @@ struct cam_iosched_softc {
 	uint32_t	this_frac;		/* Fraction of a second (1024ths) for this tick */
 	sbintime_t	last_time;		/* Last time we ticked */
 	struct control_loop cl;
+	sbintime_t	max_lat;		/* when != 0, if iop latency > max_lat, call max_lat_fcn */
+	cam_iosched_latfcn_t	latfcn;
+	void		*latarg;
 #endif
 };
 
@@ -1171,9 +1174,24 @@ void cam_iosched_sysctl_init(struct cam_iosched_softc 
 	    OID_AUTO, "load", CTLFLAG_RD,
 	    &isc->load, 0,
 	    "scaled load average / 100");
+
+	SYSCTL_ADD_U64(ctx, n,
+	    OID_AUTO, "latency_trigger", CTLFLAG_RW,
+	    &isc->max_lat, 0,
+	    "Latency treshold to trigger callbacks");
 #endif
 }
 
+void
+cam_iosched_set_latfcn(struct cam_iosched_softc *isc,
+    cam_iosched_latfcn_t fnp, void *argp)
+{
+#ifdef CAM_IOSCHED_DYNAMIC
+	isc->latfcn = fnp;
+	isc->latarg = argp;
+#endif
+}
+
 /*
  * Flush outstanding I/O. Consumers of this library don't know all the
  * queues we may keep, so this allows all I/O to be flushed in one
@@ -1510,10 +1528,21 @@ cam_iosched_bio_complete(struct cam_iosched_softc *isc
 			printf("Completing command with bio_cmd == %#x\n", bp->bio_cmd);
 	}
 
-	if (!(bp->bio_flags & BIO_ERROR) && done_ccb != NULL)
-		cam_iosched_io_metric_update(isc,
-		    cam_iosched_sbintime_t(done_ccb->ccb_h.qos.periph_data),
+	if (!(bp->bio_flags & BIO_ERROR) && done_ccb != NULL) {
+		sbintime_t sim_latency;
+		
+		sim_latency = cam_iosched_sbintime_t(done_ccb->ccb_h.qos.periph_data);
+		
+		cam_iosched_io_metric_update(isc, sim_latency,
 		    bp->bio_cmd, bp->bio_bcount);
+		/*
+		 * Debugging code: allow callbacks to the periph driver when latency max
+		 * is exceeded. This can be useful for triggering external debugging actions.
+		 */
+		if (isc->latfcn && isc->max_lat != 0 && sim_latency > isc->max_lat)
+			isc->latfcn(isc->latarg, sim_latency, bp);
+	}
+		
 #endif
 	return retval;
 }

Modified: head/sys/cam/cam_iosched.h
==============================================================================
--- head/sys/cam/cam_iosched.h	Thu Nov 15 16:02:34 2018	(r340452)
+++ head/sys/cam/cam_iosched.h	Thu Nov 15 16:02:45 2018	(r340453)
@@ -80,6 +80,8 @@ cam_iosched_sbintime_t(uintptr_t delta)
 	return (sbintime_t)((uint64_t)delta << CAM_IOSCHED_TIME_SHIFT);
 }
 
+typedef void (*cam_iosched_latfcn_t)(void *, sbintime_t, struct bio *);
+
 int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph);
 void cam_iosched_fini(struct cam_iosched_softc *);
 void cam_iosched_sysctl_init(struct cam_iosched_softc *, struct sysctl_ctx_list *, struct sysctl_oid *);
@@ -98,6 +100,7 @@ void cam_iosched_set_work_flags(struct cam_iosched_sof
 void cam_iosched_clr_work_flags(struct cam_iosched_softc *isc, uint32_t flags);
 void cam_iosched_trim_done(struct cam_iosched_softc *isc);
 int cam_iosched_bio_complete(struct cam_iosched_softc *isc, struct bio *bp, union ccb *done_ccb);
+void cam_iosched_set_latfcn(struct cam_iosched_softc *isc, cam_iosched_latfcn_t, void *);
 
 #endif
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811151602.wAFG2jjU041028>