[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