Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Oct 2017 22:53:50 +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: r325026 - head/sys/cam/ata
Message-ID:  <201710262253.v9QMrovZ009495@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Thu Oct 26 22:53:49 2017
New Revision: 325026
URL: https://svnweb.freebsd.org/changeset/base/325026

Log:
  Always send STANDBY IMMEDIATE when shutting down
  
  To save SMART data and for a drive to understand that it's been nicely
  shutdown, we need to send a STANDBY IMMEDIATE. Modify adaspindown to
  use a local CCB on the stack. When we're panicing, used
  xpt_polled_action rather than cam_periph_runccb so that we can SEND
  IMMEDIATE after we've shutdown the scheduler.
  
  Sponsored by: Netflix
  Reviewed by: scottl@, gallatin@
  Differential Revision: https://reviews.freebsd.org/D12799

Modified:
  head/sys/cam/ata/ata_da.c

Modified: head/sys/cam/ata/ata_da.c
==============================================================================
--- head/sys/cam/ata/ata_da.c	Thu Oct 26 22:53:02 2017	(r325025)
+++ head/sys/cam/ata/ata_da.c	Thu Oct 26 22:53:49 2017	(r325026)
@@ -3466,7 +3466,7 @@ adaspindown(uint8_t cmd, int flags)
 {
 	struct cam_periph *periph;
 	struct ada_softc *softc;
-	union ccb *ccb;
+	struct ccb_ataio local_ccb;
 	int error;
 
 	CAM_PERIPH_FOREACH(periph, &adadriver) {
@@ -3486,8 +3486,11 @@ adaspindown(uint8_t cmd, int flags)
 		if (bootverbose)
 			xpt_print(periph->path, "spin-down\n");
 
-		ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
-		cam_fill_ataio(&ccb->ataio,
+		memset(&local_ccb, 0, sizeof(local_ccb));
+		xpt_setup_ccb(&local_ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+		local_ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
+
+		cam_fill_ataio(&local_ccb,
 				    0,
 				    adadone,
 				    CAM_DIR_NONE | flags,
@@ -3495,14 +3498,35 @@ adaspindown(uint8_t cmd, int flags)
 				    NULL,
 				    0,
 				    ada_default_timeout*1000);
-		ata_28bit_cmd(&ccb->ataio, cmd, 0, 0, 0);
+		ata_28bit_cmd(&local_ccb, cmd, 0, 0, 0);
 
-		error = cam_periph_runccb(ccb, adaerror, /*cam_flags*/0,
-		    /*sense_flags*/ SF_NO_RECOVERY | SF_NO_RETRY,
-		    softc->disk->d_devstat);
+		if (!SCHEDULER_STOPPED()) {
+			/*
+			 * Not panicing, can just do the normal runccb
+			 * XXX should make cam_periph_runccb work while
+			 * XXX panicing... later
+			 */
+			error = cam_periph_runccb((union ccb *)&local_ccb, adaerror,
+			    /*cam_flags*/0, /*sense_flags*/ SF_NO_RECOVERY | SF_NO_RETRY,
+			    softc->disk->d_devstat);
+		} else {
+			/*
+			 * Panicing, so we have to do this by hand: do
+			 * xpt_polled_action to run the request through the SIM,
+			 * extract the error, and if the queue was frozen,
+			 * unfreeze it. cam_periph_runccb takes care of these
+			 * details, but xpt_polled_action doesn't.
+			 */
+			xpt_polled_action((union ccb *)&local_ccb);
+			error = adaerror((union ccb *)&local_ccb, 0,
+			    SF_NO_RECOVERY | SF_NO_RETRY);
+			if ((local_ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+				cam_release_devq(local_ccb.ccb_h.path,
+				    /*relsim_flags*/0, /*reduction*/0,
+				    /*timeout*/0, /*getcount_only*/0);
+		}
 		if (error != 0)
 			xpt_print(periph->path, "Spin-down disk failed\n");
-		xpt_release_ccb(ccb);
 		cam_periph_unlock(periph);
 	}
 }
@@ -3512,8 +3536,14 @@ adashutdown(void *arg, int howto)
 {
 
 	adaflush();
-	if (ada_spindown_shutdown != 0 &&
-	    (howto & (RB_HALT | RB_POWEROFF | RB_POWERCYCLE)) != 0)
+
+	/*
+	 * STANDBY IMMEDIATE flushes any volatile data to the drive so
+	 * do this always to ensure we flush a cosnsistent state to
+	 * the drive. adaspindown will ensure that we don't send this
+	 * to a drive that doesn't support it.
+	 */
+	if (ada_spindown_shutdown != 0)
 		adaspindown(ATA_STANDBY_IMMEDIATE, 0);
 }
 
@@ -3522,6 +3552,10 @@ adasuspend(void *arg)
 {
 
 	adaflush();
+	/*
+	 * SLEEP also fushes any volatile data, like STANDBY IMEDIATE,
+	 * so we don't need to send it as well.
+	 */
 	if (ada_spindown_suspend != 0)
 		adaspindown(ATA_SLEEP, CAM_DEV_QFREEZE);
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201710262253.v9QMrovZ009495>