linux-ide.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Drake <dsd@gentoo.org>
To: linux-ide@vger.kernel.org
Subject: Fixing halt/shutdown for libata spindown handling
Date: Mon, 14 May 2007 23:29:53 -0400	[thread overview]
Message-ID: <46492931.4080700@gentoo.org> (raw)

[-- Attachment #1: Type: text/plain, Size: 2194 bytes --]

Hi,

I just took a quick look into modifying halt to work as suggested for 
the new libata spindown code.

Here's how it works in Gentoo at the moment: /sbin/halt is called 
typically with the "-d -p -i -h" arguments. After doing some 
halt-specific things (such as spinning down disks per the -h argument), 
halt calls /sbin/shutdown which presumably finishes the task. This is 
with sysvinit-2.86

So, I was expecting to jump into the halt source code, find the "-h" 
argument parsing, and see code for it spinning down all the disks.

I was surprised to find that the /sbin/halt spin down implementation is 
very limited, it only works for IDE disks (by working through 
/proc/ide). This doesn't make sense to me, the libata commits state that 
userspace shutdown is spinning down libata disks.

So, this means that other distro's do it differently? I'd appreciate 
some pointers to what happens elsewhere.

I have attached the code from sysvinit which spins down the disks. It's 
not modified by the patches below.

Gentoo uses sysvinit from here:
ftp://sunsite.unc.edu/pub/Linux/system/daemons/init/sysvinit-2.86.tar.gz

Patched with:
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-docs.patch
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-shutdown-usage.patch
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-off-by-one.patch
http://distfiles.gentoo.org/distfiles/sysvinit-2.86-kexec.patch
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-execl.patch
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-utmp-64bit.patch
http://sources.gentoo.org/viewcvs.py/*checkout*/gentoo-x86/sys-apps/sysvinit/files/sysvinit-2.86-shutdown-single.patch

If I'm right and Gentoo is currently not spinning down SCSI/libata 
disks, the only /sbin/halt modification required is to write 0 into
/sys/modules/libata/parameters/spindown_compat right?

Final question: should spindown_compat be set to 0 for both shutdown and 
reboot, or just shutdown?

Thanks,
Daniel

[-- Attachment #2: hddown.c --]
[-- Type: text/x-csrc, Size: 2214 bytes --]

/*
 * hddown.c	Find all disks on the system and
 *		shut them down.
 *
 */
char *v_hddown = "@(#)hddown.c  1.02  22-Apr-2003  miquels@cistron.nl";

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>

#ifdef __linux__

#include <sys/ioctl.h>
#include <linux/hdreg.h>

#define MAX_DISKS	64
#define PROC_IDE	"/proc/ide"
#define DEV_BASE	"/dev"

/*
 *	Find all IDE disks through /proc.
 */
static int find_idedisks(char **dev, int maxdev)
{
	DIR *dd;
	FILE *fp;
	struct dirent *d;
	char buf[256];
	int i = 0;

	if ((dd = opendir(PROC_IDE)) == NULL)
		return -1;

	while ((d = readdir(dd)) != NULL) {
		if (strncmp(d->d_name, "hd", 2) != 0)
			continue;
		buf[0] = 0;
		snprintf(buf, sizeof(buf), PROC_IDE "/%s/media", d->d_name);
		if ((fp = fopen(buf, "r")) == NULL)
			continue;
		if (fgets(buf, sizeof(buf), fp) == 0 ||
		    strcmp(buf, "disk\n") != 0) {
			fclose(fp);
			continue;
		}
		fclose(fp);
		snprintf(buf, sizeof(buf), DEV_BASE "/%s", d->d_name);
		dev[i++] = strdup(buf);
		if (i >= maxdev)
			break;
	}
	closedir(dd);
	if (i < maxdev) dev[i] = NULL;

	return 0;
}

/*
 *	Put an IDE disk in standby mode.
 *	Code stolen from hdparm.c
 */
static int do_standby_idedisk(char *device)
{
#ifndef WIN_STANDBYNOW1
#define WIN_STANDBYNOW1 0xE0
#endif
#ifndef WIN_STANDBYNOW2
#define WIN_STANDBYNOW2 0x94
#endif
	unsigned char args1[4] = {WIN_STANDBYNOW1,0,0,0};
	unsigned char args2[4] = {WIN_STANDBYNOW2,0,0,0};
	int fd;

	if ((fd = open(device, O_RDWR)) < 0)
		return -1;

	if (ioctl(fd, HDIO_DRIVE_CMD, &args1) &&
	    ioctl(fd, HDIO_DRIVE_CMD, &args2))
		return -1;

	return 0;
}

/*
 *	First find all IDE disks, then put them in standby mode.
 *	This has the side-effect of flushing the writecache,
 *	which is exactly what we want on poweroff.
 */
int hddown(void)
{
	char *disks[MAX_DISKS+1];
	int i;

	if (find_idedisks(disks, MAX_DISKS) < 0)
		return -1;

	for (i = 0; disks[i] && i < MAX_DISKS; i++)
		do_standby_idedisk(disks[i]);

	return 0;
}

#else /* __linux__ */

int hddown(void)
{
	return 0;
}

#endif /* __linux__ */

#ifdef STANDALONE
int main(int argc, char **argv)
{
	return (hddown() == 0);
}
#endif


             reply	other threads:[~2007-05-15  3:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-15  3:29 Daniel Drake [this message]
2007-05-15  8:20 ` Fixing halt/shutdown for libata spindown handling Tejun Heo
2007-05-15 10:31   ` Francesco Pretto
2007-05-15 10:42     ` Tejun Heo
2007-05-17  1:16   ` Daniel Drake
2007-05-17 15:27     ` Tejun Heo
2007-05-29 22:42       ` Daniel Drake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46492931.4080700@gentoo.org \
    --to=dsd@gentoo.org \
    --cc=linux-ide@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).