From 7829692707693dbe0d055168a4b61a0f25ca16d0f7d65444d35f27b772e1370d Mon Sep 17 00:00:00 2001 From: OBS User unknown Date: Tue, 12 Jun 2007 16:39:59 +0000 Subject: [PATCH] OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/sysvinit?expand=0&rev=7 --- sysvinit-2.86-hddown.patch | 209 +++++++++++++++++++++++++++++-------- sysvinit.changes | 6 ++ sysvinit.spec | 5 +- 3 files changed, 173 insertions(+), 47 deletions(-) diff --git a/sysvinit-2.86-hddown.patch b/sysvinit-2.86-hddown.patch index a2275b0..f77f910 100644 --- a/sysvinit-2.86-hddown.patch +++ b/sysvinit-2.86-hddown.patch @@ -1,5 +1,5 @@ --- src/hddown.c -+++ src/hddown.c 2007-06-06 15:42:04.799454093 +0200 ++++ src/hddown.c 2007-06-12 16:19:45.618059522 +0200 @@ -5,6 +5,9 @@ */ char *v_hddown = "@(#)hddown.c 1.02 22-Apr-2003 miquels@cistron.nl"; @@ -10,63 +10,96 @@ #include #include #include -@@ -18,6 +21,198 @@ char *v_hddown = "@(#)hddown.c 1.02 22 +@@ -18,6 +21,315 @@ char *v_hddown = "@(#)hddown.c 1.02 22 #include #include +#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 , 2007/06/12 ++ * ++ */ +#include +#include +#include +#include ++#ifdef WORDS_BIGENDIAN ++#include ++#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 */ ++#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) ++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; -+ int fd, ret; -+ size_t len; + FILE *fp; ++ int ret; + -+ ret = snprintf(buf, sizeof(buf), SYS_BLK "/%s/removable", d->d_name); -+ if ((ret >= sizeof(buf)) || (ret < 0)) -+ goto empty; /* error */ -+ -+ fd = open(buf, O_RDONLY|O_NOCTTY); -+ if (fd < 0) { -+ if (errno != ENOENT) ++ fp = hdopen(SYS_BLK "/%s/removable", d->d_name); ++ if ((long)fp <= 0) { ++ if ((long)fp < 0) + goto empty; /* error */ + continue; /* no entry `removable' */ + } + -+ fp = fdopen(fd, "r"); -+ if (fp == (FILE*)0) { -+ close(fd); -+ goto empty; /* error */ -+ } -+ + ret = getc(fp); + fclose(fp); + + if (ret != '0') + continue; /* not a hard disk */ + -+ if (d->d_name[0] == 'h') ++ fp = hdopen(SYS_BLK "/%s/size", d->d_name); ++ if ((long)fp <= 0) { ++ if ((long)fp < 0) ++ goto empty; /* error */ ++ continue; /* no entry `size' */ ++ } ++ ++ 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 (((size_t)atoll(buf) >= (1<<28)) && flush_cache_ext(d->d_name)) ++ (*flags) |= DISK_EXTFLUSH; ++ ++ if (d->d_name[0] == 'h') { ++ (*flags) |= DISK_IS_IDE; + 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)) @@ -97,40 +130,26 @@ + if (errno != ENOENT) + goto empty; /* error */ + -+ -+ ret = snprintf(buf, sizeof(buf), SYS_BLK "/%s/device/vendor", d->d_name); -+ if ((ret >= sizeof(buf)) || (ret < 0)) -+ goto empty; /* error */ -+ -+ fd = open(buf, O_RDONLY|O_NOCTTY); -+ if (fd < 0) { -+ if (errno != ENOENT) ++ 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' */ + } + -+ fp = fdopen(fd, "r"); -+ if (fp == (FILE*)0) { -+ close(fd); -+ goto empty; /* error */ -+ } -+ + ptr = fgets(buf, sizeof(buf), fp); + fclose(fp); + if (ptr == (char*)0) + continue; /* should not happen */ + -+ if ((len = strlen(buf)) == 0) ++ ptr = strstrip(buf); ++ if (*ptr == '\0') + continue; /* should not happen */ + -+ ptr = &buf[0] + len - 1; -+ while ((ptr != &buf[0]) && ISSPACE(*ptr)) -+ ptr--; -+ *(ptr + 1) = '\0'; /* remove trailing white spaces */ -+ + if (strncmp(buf, "ATA", sizeof(buf))) + continue; /* no SATA but a real SCSI disk */ + ++ (*flags) |= (DISK_IS_IDE|DISK_IS_SATA); + break; /* new SATA disk to shutdown, out here */ + } + } @@ -145,7 +164,7 @@ + * Put an disk in standby mode. + * Code stolen from hdparm.c + */ -+static int do_standby_idedisk(char *device) ++static int do_standby_idedisk(char *device, unsigned int flags) +{ +#ifndef WIN_STANDBYNOW1 +#define WIN_STANDBYNOW1 0xE0 @@ -173,9 +192,14 @@ + if ((fd = open(buf, O_RDWR)) < 0) + return -1; + -+ if (ioctl(fd, HDIO_DRIVE_CMD, &flush1)) { ++ 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) && @@ -194,22 +218,115 @@ + */ +int hddown(void) +{ -+ DIR *blk; ++ unsigned int flags; + char *disk; ++ DIR *blk; + + if ((blk = opendir(SYS_BLK)) == (DIR*)0) + return -1; + -+ while ((disk = list_disks(blk))) -+ do_standby_idedisk(disk); ++ 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]; ++ int fd = -1, ret = 0; ++ ++ ret = snprintf(buf, sizeof(buf), DEV_BASE "/%s", device); ++ if ((ret >= sizeof(buf)) || (ret < 0)) ++ return -1; ++ ++ 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 +299,7 @@ int hddown(void) +@@ -104,7 +416,7 @@ int hddown(void) return 0; } diff --git a/sysvinit.changes b/sysvinit.changes index bea7ae6..71c7d3b 100644 --- a/sysvinit.changes +++ b/sysvinit.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Jun 12 11:42:43 CEST 2007 - werner@suse.de + +- bug #229210: check for the FLUSH CACHE EXT capability for large + disks and use this capability if available. + ------------------------------------------------------------------- Wed Jun 6 15:56:46 CEST 2007 - werner@suse.de diff --git a/sysvinit.spec b/sysvinit.spec index 83dafaf..7e63abc 100644 --- a/sysvinit.spec +++ b/sysvinit.spec @@ -22,7 +22,7 @@ Group: System/Base PreReq: coreutils Autoreqprov: on Version: 2.86 -Release: 76 +Release: 81 Summary: SysV-Style init BuildRoot: %{_tmppath}/%{name}-%{version}-build Source: sysvinit-2.86.tar.bz2 @@ -282,6 +282,9 @@ rm -rf ${RPM_BUILD_ROOT} %doc %{_mandir}/man8/startpar.8.gz %changelog +* Tue Jun 12 2007 - werner@suse.de +- bug #229210: check for the FLUSH CACHE EXT capability for large + disks and use this capability if available. * Wed Jun 06 2007 - werner@suse.de - For bug #229210: skip real SCSI disks, also flush disk cache for SATA and ATA disks.