Author: imp
Date: Mon Nov 11 17:36:52 2019
New Revision: 354622
URL: https://svnweb.freebsd.org/changeset/base/354622

Log:
  Update the softc state of the da driver before releasing the CCB.
  
  There are contexts where releasing the ccb triggers dastart() to be run
  inline. When da was written, there was always a deferral, so it didn't matter
  much. Now, with direct dispatch, we can call dastart from the dadone*
  routines. If the probe state isn't updated, then dastart will redo things with
  stale information. This normally isn't a problem, because we run the probe 
state
  machine once at boot... Except that we also run it for each open of the 
device,
  which means we can have multiple threads racing each other to try to kick off
  the probe. However, if we update the state before we release the CCB, we can
  avoid the race. While it's needed only for the probewp and proberc* states, do
  it everywhere because it won't hurt the other places.
  
  The race here happens because we reprobe dozens of times on boot when drives
  have lots of partitions.  We should consider caching this info for 1-2 seconds
  to avoid this thundering hurd.
  
  Reviewed by: scottl, ken
  Differential Revision: https://reviews.freebsd.org/D22295

Modified:
  head/sys/cam/scsi/scsi_da.c

Modified: head/sys/cam/scsi/scsi_da.c
==============================================================================
--- head/sys/cam/scsi/scsi_da.c Mon Nov 11 17:36:47 2019        (r354621)
+++ head/sys/cam/scsi/scsi_da.c Mon Nov 11 17:36:52 2019        (r354622)
@@ -4645,11 +4645,11 @@ dadone_probewp(struct cam_periph *periph, union ccb *d
        }
 
        free(csio->data_ptr, M_SCSIDA);
-       xpt_release_ccb(done_ccb);
        if ((softc->flags & DA_FLAG_CAN_RC16) != 0)
                softc->state = DA_STATE_PROBE_RC16;
        else
                softc->state = DA_STATE_PROBE_RC;
+       xpt_release_ccb(done_ccb);
        xpt_schedule(periph, priority);
        return;
 }
@@ -4709,8 +4709,8 @@ dadone_proberc(struct cam_periph *periph, union ccb *d
                         */
                        if (maxsector == 0xffffffff) {
                                free(rdcap, M_SCSIDA);
-                               xpt_release_ccb(done_ccb);
                                softc->state = DA_STATE_PROBE_RC16;
+                               xpt_release_ccb(done_ccb);
                                xpt_schedule(periph, priority);
                                return;
                        }
@@ -4816,8 +4816,8 @@ dadone_proberc(struct cam_periph *periph, union ccb *d
                                cam_periph_assert(periph, MA_OWNED);
                                softc->flags &= ~DA_FLAG_CAN_RC16;
                                free(rdcap, M_SCSIDA);
-                               xpt_release_ccb(done_ccb);
                                softc->state = DA_STATE_PROBE_RC;
+                               xpt_release_ccb(done_ccb);
                                xpt_schedule(periph, priority);
                                return;
                        }
@@ -4924,14 +4924,14 @@ dadone_proberc(struct cam_periph *periph, union ccb *d
                dadeleteflag(softc, DA_DELETE_WS10, 1);
                dadeleteflag(softc, DA_DELETE_UNMAP, 1);
 
-               xpt_release_ccb(done_ccb);
                softc->state = DA_STATE_PROBE_LBP;
+               xpt_release_ccb(done_ccb);
                xpt_schedule(periph, priority);
                return;
        }
 
-       xpt_release_ccb(done_ccb);
        softc->state = DA_STATE_PROBE_BDC;
+       xpt_release_ccb(done_ccb);
        xpt_schedule(periph, priority);
        return;
 }
@@ -4988,8 +4988,8 @@ dadone_probelbp(struct cam_periph *periph, union ccb *
        }
 
        free(lbp, M_SCSIDA);
-       xpt_release_ccb(done_ccb);
        softc->state = DA_STATE_PROBE_BLK_LIMITS;
+       xpt_release_ccb(done_ccb);
        xpt_schedule(periph, priority);
        return;
 }
@@ -5082,8 +5082,8 @@ dadone_probeblklimits(struct cam_periph *periph, union
        }
 
        free(block_limits, M_SCSIDA);
-       xpt_release_ccb(done_ccb);
        softc->state = DA_STATE_PROBE_BDC;
+       xpt_release_ccb(done_ccb);
        xpt_schedule(periph, priority);
        return;
 }
@@ -5183,8 +5183,8 @@ dadone_probebdc(struct cam_periph *periph, union ccb *
        }
 
        free(bdc, M_SCSIDA);
-       xpt_release_ccb(done_ccb);
        softc->state = DA_STATE_PROBE_ATA;
+       xpt_release_ccb(done_ccb);
        xpt_schedule(periph, priority);
        return;
 }
@@ -5323,8 +5323,8 @@ dadone_probeata(struct cam_periph *periph, union ccb *
                continue_probe = 1;
        }
        if (continue_probe != 0) {
-               xpt_release_ccb(done_ccb);
                xpt_schedule(periph, priority);
+               xpt_release_ccb(done_ccb);
                return;
        } else
                daprobedone(periph, done_ccb);
@@ -5813,8 +5813,8 @@ dadone_tur(struct cam_periph *periph, union ccb *done_
                                         /*timeout*/0,
                                         /*getcount_only*/0);
        }
-       xpt_release_ccb(done_ccb);
        softc->flags &= ~DA_FLAG_TUR_PENDING;
+       xpt_release_ccb(done_ccb);
        da_periph_release_locked(periph, DA_REF_TUR);
        return;
 }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to