Date: Wed, 13 Nov 2019 01:58:43 +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: r354668 - head/sys/cam/scsi Message-ID: <201911130158.xAD1whMM064563@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Wed Nov 13 01:58:43 2019 New Revision: 354668 URL: https://svnweb.freebsd.org/changeset/base/354668 Log: Fix a race between daopen and damediapoll When we do a daopen, we call dareprobe and wait for the results. The repoll runs the da state machine up through the DA_STATE_RC* and then exits. For removable media, we poll the device every 3 seconds with a TUR to see if it has disappeared. This introduces a race. If the removable device has lots of partitions, and if it's a little slow (like say a USB2 connected USB stick), then we can have a fair amount of time that this reporbe is going on for. If, during that time, damediapoll fires, it calls daschedule which changes the scheduling priority from NONE to NORMAL. When that happens, the careful single stepping in the da state machine is disrupted and we wind up sceduling multiple read capacity calls. The first one succeeds and releases the reference. The second one succeeds and releases the reference (and panics if the right code is compiled into the da driver). To avoid the race, only do the TUR calls while in state normal, otherwise just reschedule damediapoll. This prevents the race from happening. Modified: head/sys/cam/scsi/scsi_da.c Modified: head/sys/cam/scsi/scsi_da.c ============================================================================== --- head/sys/cam/scsi/scsi_da.c Wed Nov 13 00:53:45 2019 (r354667) +++ head/sys/cam/scsi/scsi_da.c Wed Nov 13 01:58:43 2019 (r354668) @@ -5949,6 +5949,7 @@ damediapoll(void *arg) if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) && (softc->flags & DA_FLAG_TUR_PENDING) == 0 && + softc->state == DA_STATE_NORMAL && 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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201911130158.xAD1whMM064563>