hey Petter, et al,
 I'm wondering if we can propose an updated sysvinit package for etch
that deals with the shutdown/libata issue for etch. This looks like a
pretty serious blocker for the 2.6.24 kernel proposed for etchnhalf.

 I read through the various discussions and svn history for sysvinit,
and it looks like backporting Werner Fink's patch might be the right
approach - I didn't see any simpler workaround. Attached is a patch
for this.
diff -u sysvinit-2.86.ds1/debian/patches/00list 
sysvinit-2.86.ds1/debian/patches/00list
--- sysvinit-2.86.ds1/debian/patches/00list
+++ sysvinit-2.86.ds1/debian/patches/00list
@@ -35,0 +36 @@
+92_sata-hddown
diff -u sysvinit-2.86.ds1/debian/changelog sysvinit-2.86.ds1/debian/changelog
--- sysvinit-2.86.ds1/debian/changelog
+++ sysvinit-2.86.ds1/debian/changelog
@@ -1,3 +1,11 @@
+sysvinit (2.86.ds1-38+etchnhalf.1) UNRELEASED; urgency=high
+
+  * Include patch from Werner Fink at SuSe to handle each disk individually
+    and automatically instead of guessing in the init.d script how
+    to handle them collectively (Closes: #426224).
+
+ -- dann frazier <[EMAIL PROTECTED]>  Wed, 09 Apr 2008 16:18:20 -0600
+
 sysvinit (2.86.ds1-38) unstable; urgency=medium
 
   * Medium urgency as it solve an RC bug in etch.
only in patch2:
unchanged:
--- sysvinit-2.86.ds1.orig/debian/patches/92_sata-hddown.dpatch
+++ sysvinit-2.86.ds1/debian/patches/92_sata-hddown.dpatch
@@ -0,0 +1,357 @@
+#! /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
+
[EMAIL PROTECTED]@
+diff -urNad trunk~/src/hddown.c trunk/src/hddown.c
+--- trunk~/src/hddown.c        2008-03-26 09:32:51.000000000 +0100
++++ trunk/src/hddown.c 2008-03-26 09:32:51.000000000 +0100
+@@ -5,6 +5,9 @@
+  */
+ char *v_hddown = "@(#)hddown.c  1.02  22-Apr-2003  [EMAIL PROTECTED]";
+ 
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE
++#endif
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -18,6 +21,326 @@
+ #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 <[EMAIL PROTECTED]>, 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"
+@@ -154,7 +477,7 @@
+ 
+       return (result1 ? result1 : result2);
+ }
+-
++#endif /* ! USE_SYSFS */
+ #else /* __linux__ */
+ 
+ int hddown(void)

Répondre à