[Pkg-sysvinit-commits] r1082 - in sysvinit/trunk/debian: . initscripts/etc/default initscripts/etc/init.d initscripts/man patches

pere at alioth.debian.org pere at alioth.debian.org
Sun Dec 23 09:12:24 UTC 2007


Author: pere
Date: 2007-12-23 09:12:24 +0000 (Sun, 23 Dec 2007)
New Revision: 1082

Added:
   sysvinit/trunk/debian/patches/92_sata-hddown.dpatch
Modified:
   sysvinit/trunk/debian/changelog
   sysvinit/trunk/debian/initscripts/etc/default/halt
   sysvinit/trunk/debian/initscripts/etc/init.d/halt
   sysvinit/trunk/debian/initscripts/man/halt.5
   sysvinit/trunk/debian/patches/00list
Log:
  * Rewrite libata shutdown handling to use patch from
    Werner Fink at SuSe to handle each disk individually and
    automatically instead of guessing in the init.d script how
    to handle the collectively (Closes: #426224).  This removes
    the HDDOWN default/halt variable.

Modified: sysvinit/trunk/debian/changelog
===================================================================
--- sysvinit/trunk/debian/changelog	2007-12-22 16:57:16 UTC (rev 1081)
+++ sysvinit/trunk/debian/changelog	2007-12-23 09:12:24 UTC (rev 1082)
@@ -1,3 +1,13 @@
+sysvinit (2.86.ds1-40) experimental; urgency=low
+
+  * Rewrite libata shutdown handling to use patch from
+    Werner Fink at SuSe to handle each disk individually and
+    automatically instead of guessing in the init.d script how
+    to handle the collectively (Closes: #426224).  This removes
+    the HDDOWN default/halt variable.
+
+ -- Petter Reinholdtsen <pere at debian.org>  Sun, 23 Dec 2007 10:03:48 +0100
+
 sysvinit (2.86.ds1-39) experimental; urgency=low
 
   [ Petter Reinholdtsen ]

Modified: sysvinit/trunk/debian/initscripts/etc/default/halt
===================================================================
--- sysvinit/trunk/debian/initscripts/etc/default/halt	2007-12-22 16:57:16 UTC (rev 1081)
+++ sysvinit/trunk/debian/initscripts/etc/default/halt	2007-12-23 09:12:24 UTC (rev 1082)
@@ -1,12 +1,2 @@
 # Default behaviour of shutdown -h / halt. Set to "halt" or "poweroff".
 HALT=poweroff
-
-# Should we try to spin down disks?  Note that a new enough kernel can override
-# this, and that disks are best spun down by the kernel, not by halt(8).
-# See http://linux-ata.org/shutdown.html
-#
-# Set HDDOWN to "NEVER" to not use the -h halt(8) option, or to "ALWAYS" to
-# always use the -h halt(8) option.  Leave it undefined to let the initscript
-# decide for itself.
-#HDDOWN=NEVER
-#HDDOWN=ALWAYS

Modified: sysvinit/trunk/debian/initscripts/etc/init.d/halt
===================================================================
--- sysvinit/trunk/debian/initscripts/etc/init.d/halt	2007-12-22 16:57:16 UTC (rev 1081)
+++ sysvinit/trunk/debian/initscripts/etc/init.d/halt	2007-12-23 09:12:24 UTC (rev 1082)
@@ -40,19 +40,12 @@
 		/etc/init.d/ups-monitor poweroff
 	fi
 
-	# Don't shut down drives if we're using RAID, or if the kernel can
-	# do it properly by itself, see http://linux-ata.org/shutdown.html
-	#
-	# Allow the user to override it in the default file, however
+	# Don't shut down drives if we're using RAID.
 	hddown="-h"
-	if [ "$HDDOWN" = "NEVER" ] || grep -qs '^md.*active' /proc/mdstat || \
-	   ls -1 /sys/class/scsi_disk/*/manage_start_stop >/dev/null 2>&1
+	if grep -qs '^md.*active' /proc/mdstat
 	then
 		hddown=""
 	fi
-	if [ "$HDDOWN" = "ALWAYS" ]; then
-		hddown="-h"
-	fi
 
 	# If INIT_HALT=HALT don't poweroff.
 	poweroff="-p"

Modified: sysvinit/trunk/debian/initscripts/man/halt.5
===================================================================
--- sysvinit/trunk/debian/initscripts/man/halt.5	2007-12-22 16:57:16 UTC (rev 1081)
+++ sysvinit/trunk/debian/initscripts/man/halt.5	2007-12-23 09:12:24 UTC (rev 1082)
@@ -35,15 +35,6 @@
 causes shutdown to also bring down the network interfaces (and
 thus prevent the machine from being woken up remotely).
 
-.IP \fBHDDOWN\fB
-Setting this to
-.B NEVER
-prevents /etc/init.d/halt from issuing halt -h.
-Setting it to
-.B ALWAYS
-makes /etc/init.d/halt always issue halt -h.
-Leave it undefined to let the initscript decide by itself.
-
 .SH SEE ALSO
 .BR halt "(8), " shutdown "(8)."
 

Modified: sysvinit/trunk/debian/patches/00list
===================================================================
--- sysvinit/trunk/debian/patches/00list	2007-12-22 16:57:16 UTC (rev 1081)
+++ sysvinit/trunk/debian/patches/00list	2007-12-23 09:12:24 UTC (rev 1082)
@@ -34,3 +34,4 @@
 82_killall_exclude_pids
 90_shutdown_H
 91_sulogin_lockedpw
+92_sata-hddown

Added: sysvinit/trunk/debian/patches/92_sata-hddown.dpatch
===================================================================
--- sysvinit/trunk/debian/patches/92_sata-hddown.dpatch	                        (rev 0)
+++ sysvinit/trunk/debian/patches/92_sata-hddown.dpatch	2007-12-23 09:12:24 UTC (rev 1082)
@@ -0,0 +1,356 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 92_sata-hddown.dpatch by Werner Fink and SuSe
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Make sure to shut down SATA disks properly, and handle each
+## DP: disk individually.  See also http://linux-ata.org/shutdown.html
+
+ at DPATCH@
+--- sysvinit/src/hddown.c
++++ sysvinit/src/hddown.c	2007-06-12 19:24:34.351142441 +0200
+@@ -5,6 +5,9 @@
+  */
+ char *v_hddown = "@(#)hddown.c  1.02  22-Apr-2003  miquels at cistron.nl";
+ 
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -18,6 +21,326 @@ char *v_hddown = "@(#)hddown.c  1.02  22
+ #include <sys/ioctl.h>
+ #include <linux/hdreg.h>
+ 
++#define USE_SYSFS
++#ifdef USE_SYSFS
++/*
++ * sysfs part	Find all disks on the system, list out IDE and unmanaged
++ *		SATA disks, flush the cache of those and shut them down.
++ * Author:	Werner Fink <werner at suse.de>, 2007/06/12
++ *
++ */
++#include <limits.h>
++#include <errno.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#ifdef WORDS_BIGENDIAN
++#include <byteswap.h>
++#endif
++
++#define SYS_BLK		"/sys/block"
++#define SYS_CLASS	"/sys/class/scsi_disk"
++#define DEV_BASE	"/dev"
++#define ISSPACE(c)	(((c)==' ')||((c)=='\n')||((c)=='\t')||((c)=='\v')||((c)=='\r')||((c)=='\f'))
++
++/* Used in flush_cache_ext(), compare with <linux/hdreg.h> */
++#define IDBYTES		512
++#define MASK_EXT	0xE000		/* Bit 15 shall be zero, bit 14 shall be one, bit 13 flush cache ext */
++#define TEST_EXT	0x6000
++
++/* Maybe set in list_disks() and used in do_standby_idedisk() */
++#define DISK_IS_IDE	0x00000001
++#define DISK_IS_SATA	0x00000002
++#define DISK_EXTFLUSH	0x00000004
++
++static char *strstrip(char *str);
++static FILE *hdopen(const char* const format, const char* const name);
++static int flush_cache_ext(const char *device);
++
++/*
++ *	Find all disks through /sys/block.
++ */
++static char *list_disks(DIR* blk, unsigned int* flags)
++{
++	struct dirent *d;
++
++	while ((d = readdir(blk))) {
++		*flags = 0;
++		if (d->d_name[1] == 'd' && (d->d_name[0] == 'h' || d->d_name[0] == 's')) {
++			char buf[NAME_MAX+1], lnk[NAME_MAX+1], *ptr;
++			struct stat st;
++			FILE *fp;
++			int ret;
++
++			fp = hdopen(SYS_BLK "/%s/removable", d->d_name);
++			if ((long)fp <= 0) {
++				if ((long)fp < 0)
++					goto empty;	/* error */
++				continue;		/* no entry `removable' */
++			}
++
++			ret = getc(fp);
++			fclose(fp);
++
++			if (ret != '0')
++				continue;		/* not a hard disk */
++
++			if (d->d_name[0] == 'h') {
++				(*flags) |= DISK_IS_IDE;
++				if ((ret = flush_cache_ext(d->d_name))) {
++					if (ret < 0)
++						goto empty;
++					(*flags) |= DISK_EXTFLUSH;
++				}
++				break;			/* old IDE disk not managed by kernel, out here */
++			}
++
++			ret = snprintf(buf, sizeof(buf), SYS_BLK "/%s/device", d->d_name);
++			if ((ret >= sizeof(buf)) || (ret < 0))
++				goto empty;		/* error */
++
++			ret = readlink(buf, lnk, sizeof(lnk));
++			if (ret >= sizeof(lnk))
++				goto empty;		/* error */
++			if (ret < 0) {
++				if (errno != ENOENT)
++					goto empty;	/* error */
++				continue;		/* no entry `device' */
++			}
++			lnk[ret] = '\0';
++
++			ptr = basename(lnk);
++			if (!ptr || !*ptr)
++				continue;		/* should not happen */
++
++			ret = snprintf(buf, sizeof(buf), SYS_CLASS "/%s/manage_start_stop", ptr);
++			if ((ret >= sizeof(buf)) || (ret < 0))
++				goto empty;		/* error */
++
++			ret = stat(buf, &st);
++			if (ret == 0)
++				continue;		/* disk found but managed by kernel */
++
++			if (errno != ENOENT)
++				goto empty;		/* error */
++
++			fp = hdopen(SYS_BLK "/%s/device/vendor", d->d_name);
++			if ((long)fp <= 0) {
++				if ((long)fp < 0)
++					goto empty;	/* error */
++				continue;		/* no entry `device/vendor' */
++			}
++
++			ptr = fgets(buf, sizeof(buf), fp);
++			fclose(fp);
++			if (ptr == (char*)0)
++				continue;		/* should not happen */
++
++			ptr = strstrip(buf);
++			if (*ptr == '\0')
++				continue;		/* should not happen */
++
++			if (strncmp(buf, "ATA", sizeof(buf)))
++				continue;		/* no SATA but a real SCSI disk */
++
++			(*flags) |= (DISK_IS_IDE|DISK_IS_SATA);
++			if ((ret = flush_cache_ext(d->d_name))) {
++				if (ret < 0)
++					goto empty;
++				(*flags) |= DISK_EXTFLUSH;
++			}
++			break;				/* new SATA disk to shutdown, out here */
++		}
++	}
++	if (d == (struct dirent*)0)
++		goto empty;
++	return d->d_name;
++empty:
++	return (char*)0;
++}
++
++/*
++ *	Put an disk in standby mode.
++ *	Code stolen from hdparm.c
++ */
++static int do_standby_idedisk(char *device, unsigned int flags)
++{
++#ifndef WIN_STANDBYNOW1
++#define WIN_STANDBYNOW1		0xE0
++#endif
++#ifndef WIN_STANDBYNOW2
++#define WIN_STANDBYNOW2		0x94
++#endif
++#ifndef WIN_FLUSH_CACHE_EXT
++#define WIN_FLUSH_CACHE_EXT	0xEA
++#endif
++#ifndef WIN_FLUSH_CACHE
++#define WIN_FLUSH_CACHE		0xE7
++#endif
++	unsigned char flush1[4] = {WIN_FLUSH_CACHE_EXT,0,0,0};
++	unsigned char flush2[4] = {WIN_FLUSH_CACHE,0,0,0};
++	unsigned char stdby1[4] = {WIN_STANDBYNOW1,0,0,0};
++	unsigned char stdby2[4] = {WIN_STANDBYNOW2,0,0,0};
++	char buf[NAME_MAX+1];
++	int fd, ret;
++
++	ret = snprintf(buf, sizeof(buf), DEV_BASE "/%s", device);
++	if ((ret >= sizeof(buf)) || (ret < 0))
++		return -1;
++
++	if ((fd = open(buf, O_RDWR)) < 0)
++		return -1;
++
++	switch (flags & DISK_EXTFLUSH) {
++	case DISK_EXTFLUSH:
++		if (ioctl(fd, HDIO_DRIVE_CMD, &flush1) == 0)
++			break;
++		/* Extend flush rejected, try standard flush */
++	default:
++		ioctl(fd, HDIO_DRIVE_CMD, &flush2);
++		break;
++	}
++
++	ret = ioctl(fd, HDIO_DRIVE_CMD, &stdby1) &&
++	      ioctl(fd, HDIO_DRIVE_CMD, &stdby2);
++	close(fd);
++
++	if (ret)
++		return -1;
++	return 0;
++}
++
++/*
++ *	List all disks and 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)
++{
++	unsigned int flags;
++	char *disk;
++	DIR *blk;
++
++	if ((blk = opendir(SYS_BLK)) == (DIR*)0)
++		return -1;
++
++	while ((disk = list_disks(blk, &flags)))
++		do_standby_idedisk(disk, flags);
++
++	return closedir(blk);
++}
++
++/*
++ * Strip off trailing white spaces
++ */
++static char *strstrip(char *str)
++{
++	const size_t len = strlen(str);
++	if (len) {
++		char* end = str + len - 1;
++		while ((end != str) && ISSPACE(*end))
++			end--;
++		*(end + 1) = '\0';			/* remove trailing white spaces */
++	}
++	return str;
++}
++
++/*
++ * Open a sysfs file without getting a controlling tty
++ * and return FILE* pointer.
++ */
++static FILE *hdopen(const char* const format, const char* const name)
++{
++	char buf[NAME_MAX+1];
++	FILE *fp = (FILE*)-1;
++	int fd, ret;
++	
++	ret = snprintf(buf, sizeof(buf), format, name);
++	if ((ret >= sizeof(buf)) || (ret < 0))
++		goto error;		/* error */
++
++	fd = open(buf, O_RDONLY|O_NOCTTY);
++	if (fd < 0) {
++		if (errno != ENOENT)
++			goto error;	/* error */
++		fp = (FILE*)0;
++		goto error;		/* no entry `removable' */
++	}
++
++	fp = fdopen(fd, "r");
++	if (fp == (FILE*)0)
++		close(fd);		/* should not happen */
++error:
++	return fp;
++}
++
++/*
++ * Check IDE/(S)ATA hard disk identity for
++ * the FLUSH CACHE EXT bit set.
++ */
++static int flush_cache_ext(const char *device)
++{
++#ifndef WIN_IDENTIFY
++#define WIN_IDENTIFY		0xEC
++#endif
++	unsigned char args[4+IDBYTES];
++	unsigned short *id = (unsigned short*)(&args[4]);
++	char buf[NAME_MAX+1], *ptr;
++	int fd = -1, ret = 0;
++	FILE *fp;
++
++	fp = hdopen(SYS_BLK "/%s/size", device);
++	if ((long)fp <= 0) {
++		if ((long)fp < 0)
++			return -1;	/* error */
++		goto out;		/* no entry `size' */
++	}
++
++	ptr = fgets(buf, sizeof(buf), fp);
++	fclose(fp);
++	if (ptr == (char*)0)
++		goto out;		/* should not happen */
++
++	ptr = strstrip(buf);
++	if (*ptr == '\0')
++		goto out;		/* should not happen */
++
++	if ((size_t)atoll(buf) < (1<<28))
++		goto out;		/* small disk */
++		
++	ret = snprintf(buf, sizeof(buf), DEV_BASE "/%s", device);
++	if ((ret >= sizeof(buf)) || (ret < 0))
++		return -1;		/* error */
++
++	if ((fd = open(buf, O_RDONLY|O_NONBLOCK)) < 0)
++		goto out;
++
++	memset(&args[0], 0, sizeof(args));
++	args[0] = WIN_IDENTIFY;
++	args[3] = 1;
++	if (ioctl(fd, HDIO_DRIVE_CMD, &args))
++		goto out;
++#ifdef WORDS_BIGENDIAN
++# if 0
++	{
++		const unsigned short *end = id + IDBYTES/2;
++		const unsigned short *from = id;
++		unsigned short *to = id;
++
++		while (from < end)
++			*to++ = bswap_16(*from++);
++	}
++# else
++	id[83] = bswap_16(id[83]);
++# endif
++#endif
++	if ((id[83] & MASK_EXT) == TEST_EXT)
++		ret = 1;
++out:
++	if (fd >= 0)
++		close(fd);
++	return ret;
++}
++#else /* ! USE_SYSFS */
+ #define MAX_DISKS	64
+ #define PROC_IDE	"/proc/ide"
+ #define DEV_BASE	"/dev"
+@@ -104,7 +427,7 @@ int hddown(void)
+ 
+ 	return 0;
+ }
+-
++#endif /* ! USE_SYSFS */
+ #else /* __linux__ */
+ 
+ int hddown(void)


Property changes on: sysvinit/trunk/debian/patches/92_sata-hddown.dpatch
___________________________________________________________________
Name: svn:executable
   + *




More information about the Pkg-sysvinit-commits mailing list