Summary: Re: Spin down HDD after disk sync or before power off

Oliver Fromme olli at lurza.secnetix.de
Thu Sep 16 16:19:30 UTC 2010


Tijl Coosemans wrote:
 > On Thursday 16 September 2010 16:10:22 Oliver Fromme wrote:
 > > Tijl Coosemans wrote:
 > > > I would just spin down the disk in case of a halt. An unwanted spin
 > > > down is harmless compared to an emergency shutdown and usually the
 > > > intention is to power off rather than reboot.
 > > 
 > > Is it?  When I intend to power-off, I use shutdown -p, not
 > > shutdown -h.  Quite often (but not always) when I halt a
 > > machine, I'm going to reboot to multi-user, not power off.
 > 
 > Hmm, I suppose support for power off is ubiquitous nowadays. It used to
 > be that halt meant: bring the system in a state where we can safely cut
 > the power. In that case it makes sense to let halt spin down the disks.
 > If you intend to reboot why not explicitly reboot rather than halt?

For example, I use shutdown -h in order to swap disks that
are not hot-swappable, or other kind of hardware work that
can be done while the machine is switched on.

Of course, in that particular case the disk which is about
to be swapped out should be spun down, while the others
should not.  But that's not a problem because I can use
atacontrol(8) and camcontrol(8) to spin down a specific
disk drive manually.

 > Also, to go from single to multi user mode you can just exit(1) the
 > shell.

Yes, of course, that's a different matter.

I've updated the patch for ada(4).  It includes a bug fix
(command1 vs. command2) and uses the howto flags passed to
the shutdown function.  Thanks again for pointing these out.

Best regards
   Oliver


--- ata_da.c.orig	2010-05-23 18:16:33.000000000 +0200
+++ ata_da.c	2010-09-16 17:21:10.000000000 +0200
@@ -42,6 +42,7 @@
 #include <sys/eventhandler.h>
 #include <sys/malloc.h>
 #include <sys/cons.h>
+#include <sys/reboot.h>
 #include <geom/geom_disk.h>
 #endif /* _KERNEL */
 
@@ -79,7 +80,8 @@
 	ADA_FLAG_CAN_TRIM	= 0x080,
 	ADA_FLAG_OPEN		= 0x100,
 	ADA_FLAG_SCTX_INIT	= 0x200,
-	ADA_FLAG_CAN_CFA        = 0x400
+	ADA_FLAG_CAN_CFA        = 0x400,
+	ADA_FLAG_CAN_POWERMGT   = 0x800
 } ada_flags;
 
 typedef enum {
@@ -180,6 +182,10 @@
 #define	ADA_DEFAULT_SEND_ORDERED	1
 #endif
 
+#ifndef	ADA_DEFAULT_SPINDOWN_SHUTDOWN
+#define	ADA_DEFAULT_SPINDOWN_SHUTDOWN	1
+#endif
+
 /*
  * Most platforms map firmware geometry to actual, but some don't.  If
  * not overridden, default to nothing.
@@ -191,6 +197,7 @@
 static int ada_retry_count = ADA_DEFAULT_RETRY;
 static int ada_default_timeout = ADA_DEFAULT_TIMEOUT;
 static int ada_send_ordered = ADA_DEFAULT_SEND_ORDERED;
+static int ada_spindown_shutdown = ADA_DEFAULT_SPINDOWN_SHUTDOWN;
 
 SYSCTL_NODE(_kern_cam, OID_AUTO, ada, CTLFLAG_RD, 0,
             "CAM Direct Access Disk driver");
@@ -203,6 +210,9 @@
 SYSCTL_INT(_kern_cam_ada, OID_AUTO, ada_send_ordered, CTLFLAG_RW,
            &ada_send_ordered, 0, "Send Ordered Tags");
 TUNABLE_INT("kern.cam.ada.ada_send_ordered", &ada_send_ordered);
+SYSCTL_INT(_kern_cam_ada, OID_AUTO, spindown_shutdown, CTLFLAG_RW,
+           &ada_spindown_shutdown, 0, "Spin down upon shutdown");
+TUNABLE_INT("kern.cam.ada.spindown_shutdown", &ada_spindown_shutdown);
 
 /*
  * ADA_ORDEREDTAG_INTERVAL determines how often, relative
@@ -665,6 +675,8 @@
 		softc->flags |= ADA_FLAG_CAN_48BIT;
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
 		softc->flags |= ADA_FLAG_CAN_FLUSHCACHE;
+	if (cgd->ident_data.support.command1 & ATA_SUPPORT_POWERMGT)
+		softc->flags |= ADA_FLAG_CAN_POWERMGT;
 	if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ &&
 	    cgd->inq_flags & SID_CmdQue)
 		softc->flags |= ADA_FLAG_CAN_NCQ;
@@ -1222,6 +1234,58 @@
 					 /*getcount_only*/0);
 		cam_periph_unlock(periph);
 	}
+
+	if (ada_spindown_shutdown == 0 ||
+	    (howto & (RB_HALT | RB_POWEROFF)) == 0)
+		return;
+
+	DELAY(500000);
+
+	TAILQ_FOREACH(periph, &adadriver.units, unit_links) {
+		union ccb ccb;
+
+		/* If we paniced with lock held - not recurse here. */
+		if (cam_periph_owned(periph))
+			continue;
+		cam_periph_lock(periph);
+		softc = (struct ada_softc *)periph->softc;
+		/*
+		 * We only spin-down the drive if it is capable of it..
+		 */
+		if ((softc->flags & ADA_FLAG_CAN_POWERMGT) == 0) {
+			cam_periph_unlock(periph);
+			continue;
+		}
+
+		/* XXX Hide this behind bootverbose? */
+		xpt_print(periph->path, "spin-down\n");
+
+		xpt_setup_ccb(&ccb.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
+
+		ccb.ccb_h.ccb_state = ADA_CCB_DUMP;
+		cam_fill_ataio(&ccb.ataio,
+				    1,
+				    adadone,
+				    CAM_DIR_NONE,
+				    0,
+				    NULL,
+				    0,
+				    ada_default_timeout*1000);
+
+		ata_28bit_cmd(&ccb.ataio, ATA_STANDBY_IMMEDIATE, 0, 0, 0);
+		xpt_polled_action(&ccb);
+
+		if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
+			xpt_print(periph->path, "Spin-down disk failed\n");
+
+		if ((ccb.ccb_h.status & CAM_DEV_QFRZN) != 0)
+			cam_release_devq(ccb.ccb_h.path,
+					 /*relsim_flags*/0,
+					 /*reduction*/0,
+					 /*timeout*/0,
+					 /*getcount_only*/0);
+		cam_periph_unlock(periph);
+	}
 }
 
 #endif /* _KERNEL */



-- 
Oliver Fromme, secnetix GmbH & Co. KG, Marktplatz 29, 85567 Grafing b. M.
Handelsregister: Registergericht Muenchen, HRA 74606,  Geschäftsfuehrung:
secnetix Verwaltungsgesellsch. mbH, Handelsregister: Registergericht Mün-
chen, HRB 125758,  Geschäftsführer: Maik Bachmann, Olaf Erb, Ralf Gebhart

FreeBSD-Dienstleistungen, -Produkte und mehr:  http://www.secnetix.de/bsd

"I have stopped reading Stephen King novels.
Now I just read C code instead."
        -- Richard A. O'Keefe


More information about the freebsd-hackers mailing list