Skip site navigation (1)Skip section navigation (2)
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>