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
This commit is contained in:
parent
204a1a4d4c
commit
e5436ab5af
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=340453
@ -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,6 +1174,21 @@ void cam_iosched_sysctl_init(struct cam_iosched_softc *isc,
|
||||
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
|
||||
}
|
||||
|
||||
@ -1510,10 +1528,21 @@ cam_iosched_bio_complete(struct cam_iosched_softc *isc, struct bio *bp,
|
||||
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;
|
||||
}
|
||||
|
@ -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_softc *isc, uint32_t flags);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user