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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to