Date: Thu, 22 Feb 2018 05:43:55 +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: r329815 - in head/sys/cam: . ata nvme scsi Message-ID: <201802220543.w1M5ht9k068959@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Thu Feb 22 05:43:55 2018 New Revision: 329815 URL: https://svnweb.freebsd.org/changeset/base/329815 Log: Introduce capacity flags for periphs Introduce flags word to describe the capacities of the peripheral. First bit will describe if the periph driver allows multiple outstanding TRIMS to be active in a device. Modify the I/O scheduler so that the nda driver can queue trims for a while after the first one arrives. We'll queue until we see a I/O scheduler tick, then we'll schedule as many TRIMs as allowed by other factors (currently this is slocts in the NVMe controller). This mariginally helps the read latency issues we see with reads, but sets the stage for the nda driver to do TRIM collapsing like the da and ada drivers do today. Sponsored by: Netflix Modified: head/sys/cam/ata/ata_da.c head/sys/cam/cam_iosched.c head/sys/cam/cam_iosched.h head/sys/cam/nvme/nvme_da.c head/sys/cam/scsi/scsi_da.c Modified: head/sys/cam/ata/ata_da.c ============================================================================== --- head/sys/cam/ata/ata_da.c Thu Feb 22 05:43:50 2018 (r329814) +++ head/sys/cam/ata/ata_da.c Thu Feb 22 05:43:55 2018 (r329815) @@ -1705,7 +1705,7 @@ adaregister(struct cam_periph *periph, void *arg) announce_buf = softc->announce_temp; bzero(announce_buf, ADA_ANNOUNCETMP_SZ); - if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { + if (cam_iosched_init(&softc->cam_iosched, periph, 0) != 0) { printf("adaregister: Unable to probe new device. " "Unable to allocate iosched memory\n"); free(softc, M_DEVBUF); Modified: head/sys/cam/cam_iosched.c ============================================================================== --- head/sys/cam/cam_iosched.c Thu Feb 22 05:43:50 2018 (r329814) +++ head/sys/cam/cam_iosched.c Thu Feb 22 05:43:55 2018 (r329815) @@ -68,6 +68,8 @@ static MALLOC_DEFINE(M_CAMSCHED, "CAM I/O Scheduler", #define CAM_IOSCHED_FLAG_CALLOUT_ACTIVE (1ul << 1) /* Timer has just ticked */ #define CAM_IOSCHED_FLAG_TICK (1ul << 2) + /* When set, defer trims until after next tick */ +#define CAM_IOSCHED_FLAG_TRIM_QONLY (1ul << 4) /* Periph drivers set these flags to indicate work */ #define CAM_IOSCHED_FLAG_WORK_FLAGS ((0xffffu) << 16) @@ -290,6 +292,7 @@ struct cam_iosched_softc { struct bio_queue_head trim_queue; /* scheduler flags < 16, user flags >= 16 */ uint32_t flags; + u_int caps; int sort_io_queue; #ifdef CAM_IOSCHED_DYNAMIC int read_bias; /* Read bias setting */ @@ -1064,12 +1067,16 @@ cam_iosched_cl_sysctl_fini(struct control_loop *clp) * sizeof struct cam_iosched_softc. */ int -cam_iosched_init(struct cam_iosched_softc **iscp, struct cam_periph *periph) +cam_iosched_init(struct cam_iosched_softc **iscp, struct cam_periph *periph, + u_int caps) { *iscp = malloc(sizeof(**iscp), M_CAMSCHED, M_NOWAIT | M_ZERO); if (*iscp == NULL) return ENOMEM; + (*iscp)->caps = caps; + if (caps & CAM_IOSCHED_CAP_TRIM_CLOCKED) + (*iscp)->flags |= CAM_IOSCHED_FLAG_TRIM_QONLY; #ifdef CAM_IOSCHED_DYNAMIC if (iosched_debug) printf("CAM IOSCHEDULER Allocating entry at %p\n", *iscp); @@ -1196,7 +1203,7 @@ cam_iosched_flush(struct cam_iosched_softc *isc, struc #ifdef CAM_IOSCHED_DYNAMIC static struct bio * -cam_iosched_get_write(struct cam_iosched_softc *isc) +cam_iosched_get_write(struct cam_iosched_softc *isc, bool wastick) { struct bio *bp; @@ -1305,13 +1312,45 @@ cam_iosched_next_trim(struct cam_iosched_softc *isc) * * Assumes we're called with the periph lock held. */ -struct bio * -cam_iosched_get_trim(struct cam_iosched_softc *isc) +static struct bio * +cam_iosched_get_trim(struct cam_iosched_softc *isc, bool wastick) { - if (!cam_iosched_has_more_trim(isc)) + /* + * If there's no trims, return NULL. If we're clocking out the + * trims rather than doing thins right away, this is where we + * set the queue only bit. This causes us to ignore them until + * the next clock tick. If we can't get a trim, and we're clocking + * them out, if the queue is empty or if we're rate limited, + * then set QONLY so we stop processing trims until the next + * tick. + */ + if (!cam_iosched_has_more_trim(isc)) { + if ((isc->caps & CAM_IOSCHED_CAP_TRIM_CLOCKED) && + (bioq_first(&isc->trim_queue) == NULL || +#ifdef CAM_IOSCHED_DYNAMIC + (isc->trim_stats.state_flags & IOP_RATE_LIMITED) +#else + false +#endif + )) + isc->flags |= CAM_IOSCHED_FLAG_TRIM_QONLY; return NULL; + } + /* + * If we just ticked, and we have trims, then turn off + * the queue only flag. + */ + if (wastick) + isc->flags &= ~CAM_IOSCHED_FLAG_TRIM_QONLY; + + /* + * If QONLY is set, no trims are eligble just now. + */ + if (isc->flags & CAM_IOSCHED_FLAG_TRIM_QONLY) + return NULL; + return cam_iosched_next_trim(isc); } @@ -1327,17 +1366,17 @@ cam_iosched_next_bio(struct cam_iosched_softc *isc) struct bio *bp; bool wastick; - wastick = !!(isc->flags & CAM_IOSCHED_FLAGS_TICK); - isc->flags &= ~CAM_IOSCHED_FLAGS_TICK; + wastick = !!(isc->flags & CAM_IOSCHED_FLAG_TICK); + isc->flags &= ~CAM_IOSCHED_FLAG_TICK; /* * See if we have a trim that can be scheduled. We can only send one - * at a time down, so this takes that into account. - * - * XXX newer TRIM commands are queueable. Revisit this when we - * implement them. + * at a time down, so this takes that into account for those devices + * that can only do one. In addition, some devices queue up a bunch + * of TRIMs before sending them down as a batch. */ - if ((bp = cam_iosched_get_trim(isc)) != NULL) + if ((isc->flags & CAM_IOSCHED_FLAG_TRIM_QONLY) == 0 && + (bp = cam_iosched_get_trim(isc, wastick)) != NULL) return bp; #ifdef CAM_IOSCHED_DYNAMIC @@ -1346,7 +1385,7 @@ cam_iosched_next_bio(struct cam_iosched_softc *isc) * and if so, those are next. */ if (do_dynamic_iosched) { - if ((bp = cam_iosched_get_write(isc)) != NULL) + if ((bp = cam_iosched_get_write(isc, was_tick)) != NULL) return bp; } #endif Modified: head/sys/cam/cam_iosched.h ============================================================================== --- head/sys/cam/cam_iosched.h Thu Feb 22 05:43:50 2018 (r329814) +++ head/sys/cam/cam_iosched.h Thu Feb 22 05:43:55 2018 (r329815) @@ -81,11 +81,12 @@ cam_iosched_sbintime_t(uintptr_t delta) return (sbintime_t)((uint64_t)delta << CAM_IOSCHED_TIME_SHIFT); } -int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph); +#define CAM_IOSCHED_CAP_TRIM_CLOCKED 0x1 + +int cam_iosched_init(struct cam_iosched_softc **, struct cam_periph *periph, u_int caps); void cam_iosched_fini(struct cam_iosched_softc *); void cam_iosched_sysctl_init(struct cam_iosched_softc *, struct sysctl_ctx_list *, struct sysctl_oid *); struct bio *cam_iosched_next_trim(struct cam_iosched_softc *isc); -struct bio *cam_iosched_get_trim(struct cam_iosched_softc *isc); struct bio *cam_iosched_next_bio(struct cam_iosched_softc *isc); void cam_iosched_queue_work(struct cam_iosched_softc *isc, struct bio *bp); void cam_iosched_flush(struct cam_iosched_softc *isc, struct devstat *stp, int err); Modified: head/sys/cam/nvme/nvme_da.c ============================================================================== --- head/sys/cam/nvme/nvme_da.c Thu Feb 22 05:43:50 2018 (r329814) +++ head/sys/cam/nvme/nvme_da.c Thu Feb 22 05:43:55 2018 (r329815) @@ -691,7 +691,8 @@ ndaregister(struct cam_periph *periph, void *arg) return(CAM_REQ_CMP_ERR); } - if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { + if (cam_iosched_init(&softc->cam_iosched, periph, + CAM_IOSCHED_CAP_TRIM_CLOCKED) != 0) { printf("ndaregister: Unable to probe new device. " "Unable to allocate iosched memory\n"); return(CAM_REQ_CMP_ERR); Modified: head/sys/cam/scsi/scsi_da.c ============================================================================== --- head/sys/cam/scsi/scsi_da.c Thu Feb 22 05:43:50 2018 (r329814) +++ head/sys/cam/scsi/scsi_da.c Thu Feb 22 05:43:55 2018 (r329815) @@ -2572,7 +2572,7 @@ daregister(struct cam_periph *periph, void *arg) return(CAM_REQ_CMP_ERR); } - if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { + if (cam_iosched_init(&softc->cam_iosched, periph, 0) != 0) { printf("daregister: Unable to probe new device. " "Unable to allocate iosched memory\n"); free(softc, M_DEVBUF);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802220543.w1M5ht9k068959>