Flag when we have a pending TUR. Don't schedule another one when we

have one pending. Otherwise, we can race and send two, which is
wasteful in close proximity. It can also cause the acaquire/release
count for TUR to be > 1, which is undexpected.

PR: 226510
Differential Review: https://reviews.freebsd.org/D14792
This commit is contained in:
Warner Losh 2018-03-23 16:23:15 +00:00
parent 8363051739
commit 6a6c0d5844
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=331435

View File

@ -116,7 +116,8 @@ typedef enum {
DA_FLAG_CAN_ATA_LOG = 0x008000,
DA_FLAG_CAN_ATA_IDLOG = 0x010000,
DA_FLAG_CAN_ATA_SUPCAP = 0x020000,
DA_FLAG_CAN_ATA_ZONE = 0x040000
DA_FLAG_CAN_ATA_ZONE = 0x040000,
DA_FLAG_TUR_PENDING = 0x080000
} da_flags;
typedef enum {
@ -2068,7 +2069,8 @@ daasync(void *callback_arg, u_int32_t code,
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
cam_periph_lock(periph);
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) &&
(softc->flags & DA_FLAG_TUR_PENDING) == 0) {
if (da_periph_acquire(periph, DA_REF_TUR) == 0) {
cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);
daschedule(periph);
@ -3113,6 +3115,7 @@ dastart(struct cam_periph *periph, union ccb *start_ccb)
bp = cam_iosched_next_bio(softc->cam_iosched);
if (bp == NULL) {
if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
softc->flags |= DA_FLAG_TUR_PENDING;
cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
scsi_test_unit_ready(&start_ccb->csio,
/*retries*/ da_retry_count,
@ -5570,7 +5573,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
if (daerror(done_ccb, CAM_RETRY_SELTO,
SF_RETRY_UA | SF_NO_RECOVERY | SF_NO_PRINT) ==
ERESTART)
return;
return; /* Will complete again, keep reference */
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(done_ccb->ccb_h.path,
/*relsim_flags*/0,
@ -5579,6 +5582,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
/*getcount_only*/0);
}
xpt_release_ccb(done_ccb);
softc->flags &= ~DA_FLAG_TUR_PENDING;
da_periph_release_locked(periph, DA_REF_TUR);
return;
}
@ -5700,6 +5704,7 @@ damediapoll(void *arg)
struct da_softc *softc = periph->softc;
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) &&
(softc->flags & DA_FLAG_TUR_PENDING) == 0 &&
LIST_EMPTY(&softc->pending_ccbs)) {
if (da_periph_acquire(periph, DA_REF_TUR) == 0) {
cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);