Hello community, here is the log from the commit of package hdparm for openSUSE:Factory checked in at 2012-10-03 07:45:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hdparm (Old) and /work/SRC/openSUSE:Factory/.hdparm.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hdparm", Maintainer is "[email protected]" Changes: -------- --- /work/SRC/openSUSE:Factory/hdparm/hdparm.changes 2012-03-07 13:42:36.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.hdparm.new/hdparm.changes 2012-10-03 07:45:29.000000000 +0200 @@ -1,0 +2,18 @@ +Mon Oct 1 10:53:29 UTC 2012 - [email protected] + +- update to hdparm-9.42 + - fix ordering of -S -y flags + - spelling, typo, and formatting fixes for manpage and others + - set block-count to 1 for Security commands sent via SAT (sgio) + - use FIGETBSZ to determine filesystem block size for fibmap -- needed for FAT + - fix master password revcode handling + - try and fix reg_flags (again!) for old IDE taskfile ioctls + - fixed '&&' bug in dco_identify code + - force sector dumps (read-sector, identify, ..) to use le16 output format + - proper SCT identify info courtesy of Leonid Evdokimov <[email protected]> + - updated raid1ext4trim.sh-1.5 script + - avoid HDIO_GETGEO_BIG when possible (doesn't exist in + linux-2.6.xx and beyond) + - pad secure erase timeouts by 30minutes rather than 5minutes. + +------------------------------------------------------------------- Old: ---- hdparm-9.39.tar.gz New: ---- hdparm-9.42.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hdparm.spec ++++++ --- /var/tmp/diff_new_pack.NKje3M/_old 2012-10-03 07:45:30.000000000 +0200 +++ /var/tmp/diff_new_pack.NKje3M/_new 2012-10-03 07:45:30.000000000 +0200 @@ -19,7 +19,7 @@ Name: hdparm PreReq: %insserv_prereq %fillup_prereq coreutils Provides: base:/sbin/hdparm -Version: 9.39 +Version: 9.42 Release: 0 Summary: A Program to get and set hard disk parameters License: SUSE-Permissive ++++++ hdparm-9.39.tar.gz -> hdparm-9.42.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/Changelog new/hdparm-9.42/Changelog --- old/hdparm-9.39/Changelog 2012-02-06 14:45:27.000000000 +0100 +++ new/hdparm-9.42/Changelog 2012-09-28 20:10:36.000000000 +0200 @@ -1,3 +1,18 @@ +hdparm-9.42 + - fix ordering of -S -y flags + - spelling, typo, and formatting fixes for manpage and others + - set block-count to 1 for Security commands sent via SAT (sgio) + - use FIGETBSZ to determine filesystem block size for fibmap -- needed for FAT + - fix master password revcode handling + - try and fix reg_flags (again!) for old IDE taskfile ioctls + - fixed '&&' bug in dco_identify code + - force sector dumps (read-sector, identify, ..) to use le16 output format +hdparm-9.41 + - proper SCT identify info courtesy of Leonid Evdokimov <[email protected]> + - updated raid1ext4trim.sh-1.5 script +hdparm-9.40 + - avoid HDIO_GETGEO_BIG when possible (doesn't exist in linux-2.6.xx and beyond) + - pad secure erase timeouts by 30minutes rather than 5minutes. hdparm-9.39 - added -R flag to control Read-Write-Verify feature, courtesy of Gordan Bobic - nuked leftover sgio.c.orig file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/TODO new/hdparm-9.42/TODO --- old/hdparm-9.39/TODO 2010-03-09 15:20:02.000000000 +0100 +++ new/hdparm-9.42/TODO 2012-09-28 18:51:04.000000000 +0200 @@ -1,8 +1,6 @@ Mark's TO-DO list for hdparm: ============================ -- Make parameter parsing/etc.. LBA48 safe everywhere (instead of merely u32). - - Add "wipe-drive" functionality via SCT WRITE_SAME (or manual). - Add "surface-scan" functionality via SG READ_VERIFY. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/fibmap.c new/hdparm-9.42/fibmap.c --- old/hdparm-9.39/fibmap.c 2010-11-24 22:20:17.000000000 +0100 +++ new/hdparm-9.42/fibmap.c 2012-09-28 19:40:23.000000000 +0200 @@ -222,7 +222,7 @@ int fd, err; struct stat st; __u64 start_lba = 0; - unsigned int sectors_per_block; + unsigned int sectors_per_block, blksize; if ((fd = open(file_name, O_RDONLY)) == -1) { err = errno; @@ -253,11 +253,15 @@ close(fd); return EIO; } - - sectors_per_block = st.st_blksize / sector_bytes; - printf("\n%s:\n filesystem blocksize %lu, begins at LBA %llu;" + if((err=ioctl(fd,FIGETBSZ,&blksize))){ + fprintf(stderr, "Unable to determine block size, aborting.\n"); + close(fd); + return err; + }; + sectors_per_block = blksize / sector_bytes; + printf("\n%s:\n filesystem blocksize %u, begins at LBA %llu;" " assuming %u byte sectors.\n", - file_name, (unsigned long)st.st_blksize, start_lba, sector_bytes); + file_name, blksize, start_lba, sector_bytes); printf("%12s %10s %10s %10s\n", "byte_offset", "begin_LBA", "end_LBA", "sectors"); if (st.st_size == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/geom.c new/hdparm-9.42/geom.c --- old/hdparm-9.39/geom.c 2010-11-24 22:54:48.000000000 +0100 +++ new/hdparm-9.42/geom.c 2012-05-04 15:20:57.000000000 +0200 @@ -144,7 +144,7 @@ { static struct local_hd_geometry g; static struct local_hd_big_geometry bg; - int err = 0; + int err = 0, try_getgeo_big_first = 1; if (nsectors) { err = get_sector_count(fd, nsectors); @@ -163,14 +163,17 @@ { *start_lba = result; start_lba = NULL; + try_getgeo_big_first = 0; /* if kernel has sysfs, it probably lacks GETGEO_BIG */ } else if (fd_is_raid(fd)) { - *start_lba = START_LBA_UNKNOWN; /* RAID: no such thing as a "start_lba" */ + *start_lba = START_LBA_UNKNOWN; /* RAID: no such thing as a "start_lba" */ start_lba = NULL; + try_getgeo_big_first = 0; /* no point even trying it on RAID */ } } if (cyls || heads || sects || start_lba) { - if (!ioctl(fd, HDIO_GETGEO_BIG, &bg)) { + /* Skip HDIO_GETGEO_BIG (doesn't exist) on kernels with sysfs (>= 2.6.xx) */ + if (try_getgeo_big_first && !ioctl(fd, HDIO_GETGEO_BIG, &bg)) { if (cyls) *cyls = bg.cylinders; if (heads) *heads = bg.heads; if (sects) *sects = bg.sectors; @@ -180,6 +183,11 @@ if (heads) *heads = g.heads; if (sects) *sects = g.sectors; if (start_lba) *start_lba = g.start; + } else if (!try_getgeo_big_first && !ioctl(fd, HDIO_GETGEO_BIG, &bg)) { + if (cyls) *cyls = bg.cylinders; + if (heads) *heads = bg.heads; + if (sects) *sects = bg.sectors; + if (start_lba) *start_lba = bg.start; } else { err = errno; perror(" HDIO_GETGEO failed"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/hdparm.8 new/hdparm-9.42/hdparm.8 --- old/hdparm-9.39/hdparm.8 2012-02-03 04:24:42.000000000 +0100 +++ new/hdparm-9.42/hdparm.8 2012-09-28 20:12:12.000000000 +0200 @@ -1,4 +1,4 @@ -.TH HDPARM 8 "January 2012" "Version 9.39" +.TH HDPARM 8 "September 2012" "Version 9.42" .SH NAME hdparm \- get/set SATA/IDE device parameters @@ -346,9 +346,9 @@ option should therefore only be set after one has achieved confidence in correct system operation with a chosen set of configuration settings. In practice, all that is typically necessary to test a configuration -(prior to using -k) is to verify that the drive can be read/written, +(prior to using \-k) is to verify that the drive can be read/written, and that no error logs (kernel messages) are generated in the process -(look in /var/adm/messages on most systems). +(look in /var/log/messages on most systems). .TP .I -K Set the drive\'s "keep_features_over_reset" flag. Setting this enables @@ -579,7 +579,7 @@ share a power supply. Primarily for use in large RAID setups. This feature is usually disabled and the drive is powered-up in the .B active -mode (see -C above). +mode (see \-C above). Note that a drive may also allow enabling this feature by a jumper. Some SATA drives support the control of this feature by pin 11 of the SATA power connector. In these cases, this command may be @@ -674,7 +674,7 @@ provides a safe fix for the problem for use with earlier kernels. .TP .I -v -Display some basic settings, similar to -acdgkmur for IDE. +Display some basic settings, similar to \-acdgkmur for IDE. This is also the default behaviour when no options are specified. .TP .I --verbose @@ -767,19 +767,19 @@ .B USE AT YOUR OWN RISK. .TP .I --security-help -Display terse usage info for all of the --security-* options. +Display terse usage info for all of the \--security-* options. .TP .I --security-freeze Freeze the drive\'s security settings. The drive does not accept any security commands until next power-on reset. -Use this function in combination with --security-unlock to protect drive +Use this function in combination with \--security-unlock to protect drive from any attempt to set a new password. Can be used standalone, too. No other options are permitted on the command line with this one. .TP .I --security-unlock PWD Unlock the drive, using password PWD. Password is given as an ASCII string and is padded with NULs to reach 32 bytes. -The applicable drive password is selected with the --user-master switch +The applicable drive password is selected with the \--user-master switch (default is "user" password). No other options are permitted on the command line with this one. .TP @@ -790,15 +790,15 @@ Use the special password .B NULL to set an empty password. -The applicable drive password is selected with the --user-master switch +The applicable drive password is selected with the \--user-master switch (default is "user" password) -and the applicable security mode with the --security-mode switch. +and the applicable security mode with the \--security-mode switch. No other options are permitted on the command line with this one. .TP .I --security-disable PWD Disable drive locking, using password PWD. Password is given as an ASCII string and is padded with NULs to reach 32 bytes. -The applicable drive password is selected with the --user-master switch +The applicable drive password is selected with the \--user-master switch (default is "user" password). No other options are permitted on the command line with this one. .TP @@ -809,7 +809,7 @@ Use the special password .B NULL to represent an empty password. -The applicable drive password is selected with the --user-master switch +The applicable drive password is selected with the \--user-master switch (default is "user" password). No other options are permitted on the command line with this one. .TP @@ -817,15 +817,15 @@ Enhanced erase (locked) drive, using password PWD .B (DANGEROUS). Password is given as an ASCII string and is padded with NULs to reach 32 bytes. -The applicable drive password is selected with the --user-master switch +The applicable drive password is selected with the \--user-master switch (default is "user" password). No other options are permitted on the command line with this one. .TP .I --user-master USER Specifies which password (user/master) to select. .B Defaults to "user" password. -Only useful in combination with --security-unlock, --security-set-pass, ---security-disable, --security-erase or --security-erase-enhanced. +Only useful in combination with \--security-unlock, \--security-set-pass, +\--security-disable, \--security-erase or \--security-erase-enhanced. u user password m master password @@ -833,7 +833,7 @@ .I --security-mode MODE Specifies which security mode (high/maximum) to set. .B Defaults to high. -Only useful in combination with --security-set-pass. +Only useful in combination with \--security-set-pass. h high security m maximum security @@ -850,7 +850,7 @@ a few drive/controller combinations are not 100% compatible. Filesystem corruption may result. Backup everything before experimenting! .PP -Some options (e.g. -r for SCSI) may not work with old kernels as +Some options (e.g. \-r for SCSI) may not work with old kernels as necessary ioctl()\'s were not supported. .PP Although this utility is intended primarily for use with SATA/IDE hard disk diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/hdparm.c new/hdparm-9.42/hdparm.c --- old/hdparm-9.39/hdparm.c 2012-02-03 04:24:33.000000000 +0100 +++ new/hdparm-9.42/hdparm.c 2012-09-28 20:12:01.000000000 +0200 @@ -1,5 +1,7 @@ -/* hdparm.c - Command line interface to get/set hard disk parameters */ -/* - by Mark Lord (C) 1994-2012 -- freely distributable */ +/* + * hdparm.c - Command line interface to get/set hard disk parameters. + * - by Mark Lord (C) 1994-2012 -- freely distributable. + */ #define _LARGEFILE64_SOURCE /*for lseek64*/ #define _BSD_SOURCE /* for strtoll() */ #include <unistd.h> @@ -23,6 +25,7 @@ #include <linux/types.h> #include <linux/fs.h> #include <linux/major.h> +#include <endian.h> #include <asm/byteorder.h> #include "hdparm.h" @@ -35,7 +38,7 @@ extern const char *minor_str[]; -#define VERSION "v9.39" +#define VERSION "v9.42" #ifndef O_DIRECT #define O_DIRECT 040000 /* direct disk access, not easily obtained from headers */ @@ -719,7 +722,7 @@ if (timeout < estimate) timeout = estimate; } else { - timeout = (timeout * 2) + 5; /* Add on a 5min margin */ + timeout = (timeout * 2) + 30; /* Add on a 30min margin */ } } } @@ -749,6 +752,8 @@ r->dphase = TASKFILE_DPHASE_PIO_OUT; r->obytes = 512; r->lob.command = security_command; + r->oflags.lob.nsect = 1; + r->lob.nsect = 1; data = (__u8*)r->data; data[0] = security_master & 0x01; memcpy(data+2, security_password, 32); @@ -777,7 +782,7 @@ if (!id) exit(EIO); revcode = id[92]; - if (revcode == 0xffff) + if (revcode == 0xfffe) revcode = 0; revcode += 1; data[34] = revcode; @@ -922,8 +927,18 @@ unsigned int i; for (i = 0; i < (count*256/8); ++i) { - printf("%04x %04x %04x %04x %04x %04x %04x %04x\n", w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); +#if 0 + printf("%04x %04x %04x %04x %04x %04x %04x %04x\n", + w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]); w += 8; +#else + int word; + for (word = 0; word < 8; ++word) { + printf("%04x", le16toh(w[0])); + ++w; + putchar(word == 7 ? '\n' : ' '); + } +#endif } } @@ -1517,7 +1532,7 @@ " --security-erase PASSWD Erase a (locked) drive.\n" " --security-erase-enhanced PASSWD Enhanced-erase a (locked) drive.\n" "\n" - " The above four commands may optionally be preceeded by these options:\n" + " The above four commands may optionally be preceded by these options:\n" " --security-mode LEVEL Use LEVEL to select security level:\n" " h high security (default).\n" " m maximum security.\n" @@ -1841,6 +1856,17 @@ if (!wcache) err = flush_wcache(fd); } + if (set_standby) { + __u8 args[4] = {ATA_OP_SETIDLE,standby,0,0}; + if (get_standby) { + printf(" setting standby to %u", standby); + interpret_standby(); + } + if (do_drive_cmd(fd, args, 0)) { + err = errno; + perror(" HDIO_DRIVE_CMD(setidle) failed"); + } + } if (set_standbynow) { __u8 args1[4] = {ATA_OP_STANDBYNOW1,0,0,0}; __u8 args2[4] = {ATA_OP_STANDBYNOW2,0,0,0}; @@ -1917,17 +1943,6 @@ perror(" HDIO_DRIVE_CMD(seagatepwrsave) failed"); } } - if (set_standby) { - __u8 args[4] = {ATA_OP_SETIDLE,standby,0,0}; - if (get_standby) { - printf(" setting standby to %u", standby); - interpret_standby(); - } - if (do_drive_cmd(fd, args, 0)) { - err = errno; - perror(" HDIO_DRIVE_CMD(setidle) failed"); - } - } if (set_busstate) { if (get_busstate) printf(" setting bus state to %d (%s)\n", busstate, busstate_str(busstate)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/hdparm.lsm new/hdparm-9.42/hdparm.lsm --- old/hdparm-9.39/hdparm.lsm 2012-02-03 04:26:50.000000000 +0100 +++ new/hdparm-9.42/hdparm.lsm 2012-09-28 20:12:45.000000000 +0200 @@ -1,9 +1,12 @@ Begin4 Title: hdparm -Version: 9.39 -Entered-date: 2012-02-02 +Version: 9.42 +Entered-date: 2012-09-28 Description: hdparm - get/set hard disk parameters for Linux SATA/IDE drives. - v9.38 Added -R, courtesy of Gordan Bobic + v9.42 lots of fixes from the sourceforge queue + v9.41 updated SCT identification, other small fixes. + v9.40 internal release + v9.39 Added -R, courtesy of Gordan Bobic v9.38 Added -J, fixed erase timeouts, updated wiper.sh v9.37 Enable --fibmap to work on RAID1; other tweaks v9.36 manpage updates, wiper.sh version 3.1 @@ -113,7 +116,7 @@ Maintained-by: [email protected] (Mark Lord) Primary-site: http://sourceforge.net/projects/hdparm/ Alternate-site: http://www.ibiblio.org/pub/Linux/system/hardware - 127K hdparm-9.39.tar.gz + 127K hdparm-9.42.tar.gz 4K hdparm.lsm Platforms: Linux Copying-policy: BSD License diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/identify.c new/hdparm-9.42/identify.c --- old/hdparm-9.39/identify.c 2011-12-04 23:49:22.000000000 +0100 +++ new/hdparm-9.42/identify.c 2012-09-28 18:55:17.000000000 +0200 @@ -514,8 +514,8 @@ "SCT Data Tables (AC5)", /* word 206 bit 5 */ "SCT Features Control (AC4)", /* word 206 bit 4 */ "SCT Error Recovery Control (AC3)", /* word 206 bit 3 */ - "SCT LBA Segment Access (AC2)", /* word 206 bit 2 */ - "SCT Long Sector Access (AC1)", /* word 206 bit 1 */ + "SCT Write Same (AC2)", /* word 206 bit 2 */ + "SCT Read/Write Long (AC1), obsolete", /* word 206 bit 1: obsolete per T13/e08153r1 */ "SMART Command Transport (SCT) feature set" /* word 206 bit 0 */ }; @@ -1473,7 +1473,7 @@ } putchar('\n'); - if (dco[8] && 0x1f) { + if (dco[8] & 0x1f) { printf("\tSATA command/feature sets:\n\t\t"); if (dco[0] < 2) printf(" (?):"); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/sgio.h new/hdparm-9.42/sgio.h --- old/hdparm-9.39/sgio.h 2012-01-06 15:45:00.000000000 +0100 +++ new/hdparm-9.42/sgio.h 2012-09-28 19:25:46.000000000 +0200 @@ -115,7 +115,8 @@ TASKFILE_DPHASE_PIO_OUT = 4, /* ide: TASKFILE_OUT */ }; -struct reg_flags { +union reg_flags { + unsigned all :16; union { unsigned lob_all : 8; struct { @@ -142,7 +143,7 @@ unsigned command : 1; } hob; }; -}; +} __attribute__((packed)); struct taskfile_regs { __u8 data; @@ -158,8 +159,8 @@ struct hdio_taskfile { struct taskfile_regs lob; struct taskfile_regs hob; - struct reg_flags oflags; - struct reg_flags iflags; + union reg_flags oflags; + union reg_flags iflags; int dphase; int cmd_req; /* IDE command_type */ unsigned long obytes; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/sgio.h.xx new/hdparm-9.42/sgio.h.xx --- old/hdparm-9.39/sgio.h.xx 1970-01-01 01:00:00.000000000 +0100 +++ new/hdparm-9.42/sgio.h.xx 2012-09-28 19:25:46.000000000 +0200 @@ -0,0 +1,233 @@ +/* prototypes and stuff for ATA command ioctls */ + +#include <linux/types.h> + +enum { + ATA_OP_DSM = 0x06, // Data Set Management (TRIM) + ATA_OP_READ_PIO = 0x20, + ATA_OP_READ_PIO_ONCE = 0x21, + ATA_OP_READ_LONG = 0x22, + ATA_OP_READ_LONG_ONCE = 0x23, + ATA_OP_READ_PIO_EXT = 0x24, + ATA_OP_READ_DMA_EXT = 0x25, + ATA_OP_READ_FPDMA = 0x60, // NCQ + ATA_OP_WRITE_PIO = 0x30, + ATA_OP_WRITE_LONG = 0x32, + ATA_OP_WRITE_LONG_ONCE = 0x33, + ATA_OP_WRITE_PIO_EXT = 0x34, + ATA_OP_WRITE_DMA_EXT = 0x35, + ATA_OP_WRITE_FPDMA = 0x61, // NCQ + ATA_OP_READ_VERIFY = 0x40, + ATA_OP_READ_VERIFY_ONCE = 0x41, + ATA_OP_READ_VERIFY_EXT = 0x42, + ATA_OP_WRITE_UNC_EXT = 0x45, // lba48, no data, uses feat reg + ATA_OP_FORMAT_TRACK = 0x50, + ATA_OP_DOWNLOAD_MICROCODE = 0x92, + ATA_OP_STANDBYNOW2 = 0x94, + ATA_OP_CHECKPOWERMODE2 = 0x98, + ATA_OP_SLEEPNOW2 = 0x99, + ATA_OP_PIDENTIFY = 0xa1, + ATA_OP_READ_NATIVE_MAX = 0xf8, + ATA_OP_READ_NATIVE_MAX_EXT = 0x27, + ATA_OP_SMART = 0xb0, + ATA_OP_DCO = 0xb1, + ATA_OP_ERASE_SECTORS = 0xc0, + ATA_OP_READ_DMA = 0xc8, + ATA_OP_WRITE_DMA = 0xca, + ATA_OP_DOORLOCK = 0xde, + ATA_OP_DOORUNLOCK = 0xdf, + ATA_OP_STANDBYNOW1 = 0xe0, + ATA_OP_IDLEIMMEDIATE = 0xe1, + ATA_OP_SETIDLE = 0xe3, + ATA_OP_SET_MAX = 0xf9, + ATA_OP_SET_MAX_EXT = 0x37, + ATA_OP_SET_MULTIPLE = 0xc6, + ATA_OP_CHECKPOWERMODE1 = 0xe5, + ATA_OP_SLEEPNOW1 = 0xe6, + ATA_OP_FLUSHCACHE = 0xe7, + ATA_OP_FLUSHCACHE_EXT = 0xea, + ATA_OP_IDENTIFY = 0xec, + ATA_OP_SETFEATURES = 0xef, + ATA_OP_SECURITY_SET_PASS = 0xf1, + ATA_OP_SECURITY_UNLOCK = 0xf2, + ATA_OP_SECURITY_ERASE_PREPARE = 0xf3, + ATA_OP_SECURITY_ERASE_UNIT = 0xf4, + ATA_OP_SECURITY_FREEZE_LOCK = 0xf5, + ATA_OP_SECURITY_DISABLE = 0xf6, + ATA_OP_VENDOR_SPECIFIC_0x80 = 0x80, +}; + +/* + * Some useful ATA register bits + */ +enum { + ATA_USING_LBA = (1 << 6), + ATA_STAT_DRQ = (1 << 3), + ATA_STAT_ERR = (1 << 0), +}; + +/* + * Useful parameters for init_hdio_taskfile(): + */ +enum { RW_READ = 0, + RW_WRITE = 1, + LBA28_OK = 0, + LBA48_FORCE = 1, +}; + +/* + * Definitions and structures for use with SG_IO + ATA_16: + */ +struct ata_lba_regs { + __u8 feat; + __u8 nsect; + __u8 lbal; + __u8 lbam; + __u8 lbah; +}; +struct ata_tf { + __u8 dev; + __u8 command; + __u8 error; + __u8 status; + __u8 is_lba48; + struct ata_lba_regs lob; + struct ata_lba_regs hob; +}; + +/* + * Definitions and structures for use with HDIO_DRIVE_TASKFILE: + */ + +enum { + /* + * These (redundantly) specify the category of the request + */ + TASKFILE_CMD_REQ_NODATA = 0, /* ide: IDE_DRIVE_TASK_NO_DATA */ + TASKFILE_CMD_REQ_IN = 2, /* ide: IDE_DRIVE_TASK_IN */ + TASKFILE_CMD_REQ_OUT = 3, /* ide: IDE_DRIVE_TASK_OUT */ + TASKFILE_CMD_REQ_RAW_OUT= 4, /* ide: IDE_DRIVE_TASK_RAW_WRITE */ + /* + * These specify the method of transfer (pio, dma, multi, ..) + */ + TASKFILE_DPHASE_NONE = 0, /* ide: TASKFILE_IN */ + TASKFILE_DPHASE_PIO_IN = 1, /* ide: TASKFILE_IN */ + TASKFILE_DPHASE_PIO_OUT = 4, /* ide: TASKFILE_OUT */ +}; + +union reg_flags { + unsigned all :16; + union { + unsigned lob_all : 8; + struct { + unsigned data : 1; + unsigned feat : 1; + unsigned lbal : 1; + unsigned nsect : 1; + unsigned lbam : 1; + unsigned lbah : 1; + unsigned dev : 1; + unsigned command : 1; + } lob; + }; + union { + unsigned hob_all : 8; + struct { + unsigned data : 1; + unsigned feat : 1; + unsigned lbal : 1; + unsigned nsect : 1; + unsigned lbam : 1; + unsigned lbah : 1; + unsigned dev : 1; + unsigned command : 1; + } hob; + }; +} __attribute__((packed)); + +struct taskfile_regs { + __u8 data; + __u8 feat; + __u8 nsect; + __u8 lbal; + __u8 lbam; + __u8 lbah; + __u8 dev; + __u8 command; +}; + +struct hdio_taskfile { + struct taskfile_regs lob; + struct taskfile_regs hob; + union reg_flags oflags; + union reg_flags iflags; + int dphase; + int cmd_req; /* IDE command_type */ + unsigned long obytes; + unsigned long ibytes; + __u16 data[0]; +}; + +struct scsi_sg_io_hdr { + int interface_id; + int dxfer_direction; + unsigned char cmd_len; + unsigned char mx_sb_len; + unsigned short iovec_count; + unsigned int dxfer_len; + void * dxferp; + unsigned char * cmdp; + void * sbp; + unsigned int timeout; + unsigned int flags; + int pack_id; + void * usr_ptr; + unsigned char status; + unsigned char masked_status; + unsigned char msg_status; + unsigned char sb_len_wr; + unsigned short host_status; + unsigned short driver_status; + int resid; + unsigned int duration; + unsigned int info; +}; + +#ifndef SG_DXFER_NONE + #define SG_DXFER_NONE -1 + #define SG_DXFER_TO_DEV -2 + #define SG_DXFER_FROM_DEV -3 + #define SG_DXFER_TO_FROM_DEV -4 +#endif + +#define SG_READ 0 +#define SG_WRITE 1 + +#define SG_PIO 0 +#define SG_DMA 1 + +#define SG_CHECK_CONDITION 0x02 +#define SG_DRIVER_SENSE 0x08 + +#define SG_ATA_16 0x85 +#define SG_ATA_16_LEN 16 + +#define SG_ATA_12 0xa1 +#define SG_ATA_12_LEN 12 + +#define SG_ATA_LBA48 1 +#define SG_ATA_PROTO_NON_DATA ( 3 << 1) +#define SG_ATA_PROTO_PIO_IN ( 4 << 1) +#define SG_ATA_PROTO_PIO_OUT ( 5 << 1) +#define SG_ATA_PROTO_DMA ( 6 << 1) +#define SG_ATA_PROTO_UDMA_IN (11 << 1) /* not yet supported in libata */ +#define SG_ATA_PROTO_UDMA_OUT (12 << 1) /* not yet supported in libata */ + +void tf_init (struct ata_tf *tf, __u8 ata_op, __u64 lba, unsigned int nsect); +__u64 tf_to_lba (struct ata_tf *tf); +int sg16 (int fd, int rw, int dma, struct ata_tf *tf, void *data, unsigned int data_bytes, unsigned int timeout_secs); +int do_drive_cmd (int fd, unsigned char *args, unsigned int timeout); +int do_taskfile_cmd (int fd, struct hdio_taskfile *r, unsigned int timeout_secs); +int dev_has_sgio (int fd); +void init_hdio_taskfile (struct hdio_taskfile *r, __u8 ata_op, int rw, int force_lba48, + __u64 lba, unsigned int nsect, int data_bytes); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/wiper/Changelog new/hdparm-9.42/wiper/Changelog --- old/hdparm-9.39/wiper/Changelog 2011-02-21 15:59:43.000000000 +0100 +++ new/hdparm-9.42/wiper/Changelog 2012-09-28 19:33:15.000000000 +0200 @@ -1,3 +1,5 @@ +wiper.sh-3.5 + - don't skip Group 0 on ext* filesystems wiper.sh-3.4 - updated to allow all SCSI_DISK_MAJOR numbers, not just "8" wiper.sh-3.3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/wiper/contrib/README.contrib new/hdparm-9.42/wiper/contrib/README.contrib --- old/hdparm-9.39/wiper/contrib/README.contrib 2010-11-07 16:06:44.000000000 +0100 +++ new/hdparm-9.42/wiper/contrib/README.contrib 2012-09-28 18:47:18.000000000 +0200 @@ -1,7 +1,7 @@ Contributed scripts and notes from others (untested by me). =========================================================== -raid1ext4trim.sh-1.4 +raid1ext4trim.sh-1.5 Similar to wiper.sh, but for ext4/RAID1 mirrors. By Chris Caputo <[email protected]>. Adapted from wiper.sh (ver 2.6 by Mark Lord). diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/wiper/contrib/raid1ext4trim.sh-1.4 new/hdparm-9.42/wiper/contrib/raid1ext4trim.sh-1.4 --- old/hdparm-9.39/wiper/contrib/raid1ext4trim.sh-1.4 2010-11-07 16:05:35.000000000 +0100 +++ new/hdparm-9.42/wiper/contrib/raid1ext4trim.sh-1.4 1970-01-01 01:00:00.000000000 +0100 @@ -1,407 +0,0 @@ -#!/bin/bash -# -# SSD TRIM utility for live RAID1 mirrored ext4 drives. -# -# By Chris Caputo. Adapted from wiper.sh (ver 2.6) by Mark Lord. - -VERSION=1.4 - -# Copyright (C) 2010 Chris Caputo. All rights reserved. -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License Version 2, -# as published by the Free Software Foundation. -# -# This program is distributed in the hope that it would be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -function usage_error(){ - echo "Usage:" - echo " ${0##*/} [--verbose] [--commit] [--reserve=#megs] [--max-ranges=#ranges] <raid_dev> <fsdir>" - echo "Examples:" - echo " ${0##*/} --verbose --commit --reserve=100 --max-ranges=512 md0 /" - echo " ${0##*/} --verbose --verbose md1 /boot" - echo - echo "Note: For best results, this script should be run on each ext4-based filesystem present on a RAID1 array." - echo - exit 1 -} - -echo "${0##*/}: TRIM utility for live RAID1 ext4 SATA SSDs, version $VERSION, by Chris Caputo, based on Mark Lord's wiper.sh." -echo - -## Parameter parsing for the main script. -## - -export verbose=0 -commit="" -reservemegs=0 -max_ranges=0 -argc=$# -raiddev="" -fsdir="" -while [ $argc -gt 0 ]; do - if [ "$1" = "--commit" ]; then - commit=yes - elif [ "$1" = "--verbose" ]; then - verbose=$((verbose + 1)) - elif [[ "$1" =~ --reserve=[[:digit:]] ]]; then - reservemegs=${1##--reserve=} - elif [[ "$1" =~ --max-ranges=[[:digit:]] ]]; then - max_ranges=${1##--max-ranges=} - elif [ "$1" = "" ]; then - usage_error - else - if [ "$raiddev" = "" ]; then - raiddev=${1##*/} - elif [ "$fsdir" = "" ]; then - fsdir=$1 - else - echo "$1: too many arguments, aborting." - exit 1 - fi - fi - argc=$((argc - 1)) - shift -done -[ "$raiddev" = "" ] && usage_error -[ "$fsdir" = "" ] && usage_error - -## Check --reserve number. -## - -isdigit () # Tests whether *entire string* is numerical. -{ # In other words, tests for integer variable. - [ $# -eq 1 ] || return -1 - - case $1 in - *[!0-9]*|"") return -1;; - *) return 0;; - esac -} - -if ! isdigit "$reservemegs" ; then - echo "'$reservemegs' is not numerical" - exit 1 -fi -if ! isdigit "$max_ranges" ; then - echo "'$max_ranges' is not numerical" - exit 1 -fi - -if [ $reservemegs -eq 0 ]; then - echo "Reserve defaulting to 10 megabytes." - reservemegs=10 -fi -reservekilos=$((reservemegs * 1024)) - -## Find a required program, or else give a nicer error message than we'd otherwise see: -## -function find_prog(){ - prog="$1" - if [ ! -x "$prog" ]; then - prog="${prog##*/}" - p=`type -f -P "$prog" 2>/dev/null` - if [ "$p" = "" ]; then - echo "$1: needed but not found, aborting." - exit 1 - fi - prog="$p" - [ $verbose -gt 0 ] && echo " --> using $prog instead of $1" - fi - echo "$prog" -} - -## Ensure we have most of the necessary utilities available before trying to proceed: -## -hash -r ## Refresh bash's cached PATH entries -HDPARM=`find_prog /sbin/hdparm` || exit 1 -GAWK=`find_prog /usr/bin/gawk` || exit 1 -GREP=`find_prog /bin/grep` || exit 1 -ID=`find_prog /usr/bin/id` || exit 1 -LS=`find_prog /bin/ls` || exit 1 -DF=`find_prog /bin/df` || exit 1 -RM=`find_prog /bin/rm` || exit 1 - -[ $verbose -gt 1 ] && HDPARM="$HDPARM --verbose" - -## I suppose this will confuse the three SELinux users out there: -## -if [ `$ID -u` -ne 0 ]; then - echo "Only the super-user can use this (try \"sudo $0\" instead), aborting." - exit 1 -fi - -## We need a very modern hdparm, for its --fallocate and --trim-sector-ranges-stdin flags: -## Version 9.25 added automatic determination of safe max-size of TRIM commands. -## -HDPVER=`$HDPARM -V | $GAWK '{gsub("[^0-9.]","",$2); if ($2 > 0) print ($2 * 100); else print 0; exit(0)}'` -if [ $HDPVER -lt 925 ]; then - echo "$HDPARM: version >= 9.25 is required, aborting." - exit 1 -fi - -## Check that this is a RAID1 device. -## -if ! $GREP raid1 /sys/block/$raiddev/md/level 1>/dev/null ; then - echo "$raiddev is not a RAID1 array." - exit 1 -fi - -## Get list of slave devices in the RAID1 mirror. -## -slaves=(`$LS /sys/block/$raiddev/slaves`) -#slaves=(sda sdb sdc) -#slaves=(md0) - -## Check for DEVTYPE disk and TRIM support on each slave. -## -index=0 -for slave in "${slaves[@]}" -do - # Check that slave is of DEVTYPE disk. - if ! $GREP "DEVTYPE=disk" /sys/block/$slave/uevent 1>/dev/null ; then - echo "$slave is not a whole disk. This program only works with full-disk RAID1, not RAID1 partitions." - exit 1 - fi - - # Check that slave has TRIM support. Exclude if not. - if ! $HDPARM -I /dev/$slave | $GREP -i '[ ][*][ ]*Data Set Management TRIM supported' &>/dev/null ; then - echo "$slave doesn't appear to support TRIM, per $HDPARM. Excluding." - unset slaves[index] - fi - - let "index = $index + 1" -done -if [ "${slaves[0]}" = "" ]; then - echo "No constituent of $raiddev array supports TRIM. Aborting." - exit 1 -fi - -## Check that fsdir is on an ext4 volume. -## -lines=`$DF --type=ext4 $fsdir 2>/dev/null | $GREP -v ^Filesystem | wc -l` -if [ $lines -ne 1 ]; then - echo "'$fsdir' does not appear to be on an ext4 filesystem. Aborting." - exit 1 -fi - -## Check that fsdir is a directory. -## -if [ ! -d $fsdir ]; then - echo "'$fsdir' is not a directory. Aborting." - exit 1 -fi - -## Check free space & calculate tmpfile size. -## -freesize=`$DF -P -B 1024 $fsdir | $GAWK '{r=$4}END{print r}'` -if [ "$freesize" = "" ]; then - echo "'$fsdir' is unknown to '$DF'. Aborting." - exit 1 -fi -if [ $freesize -lt $reservekilos ]; then - echo "'$fsdir' available space of $freesize KB is less than the $reservekilos KB to be reserved for the TRIM operation. Aborting." >&2 - exit 1 -fi -tmpsize=$((freesize - reservekilos)) -tmpfile="$fsdir/${0##*/}_TMPFILE.$$" - -## Clean up tmpfile (if any) and exit: -## -function do_cleanup(){ - if [ -e $tmpfile ]; then - echo "Removing temporary file '$tmpfile'..." - $RM -f $tmpfile - if [ -e $tmpfile ]; then - echo "Failed to remove '$tmpfile'!!!" - fi - fi - [ $1 -eq 0 ] && echo "Done." - [ $1 -eq 0 ] || echo "Aborted." >&2 - exit $1 -} - -## Prepare signal handling, in case we get interrupted while $tmpfile exists: -## -function do_abort(){ - echo - do_cleanup 1 -} -trap do_abort SIGTERM -trap do_abort SIGQUIT -trap do_abort SIGINT -trap do_abort SIGHUP -trap do_abort SIGPIPE - -## Do the fallocate. -## This is where we finally discover whether the filesystem actually -## supports --fallocate or not. Some folks will be disappointed here. -## -## Note that --fallocate does not actually write any file data to fsdev, -## but rather simply allocates formerly-free space to the tmpfile. -## -echo -n "Creating temporary file (${tmpsize} KB '$tmpfile') ... " -if ! $HDPARM --fallocate "${tmpsize}" $tmpfile ; then - echo "This kernel may not support 'fallocate'. Aborting." - exit 1 -fi -echo - -## Verify that slaves and RAID1 mirror have same base LBA. First add a test -## string to the tmpfile. "date" is used since it is ever changing. -## -TESTSTR=`date` -echo "$TESTSTR" >> $tmpfile -sync # this is critical -SECTOR_BYTES=`$HDPARM --fibmap $tmpfile | \ - $GREP "byte sectors" | \ - $GAWK '{print $9}'` -LAST_EXTENT_SECTOR_COUNT=`$HDPARM --fibmap $tmpfile | \ - tail -1 | \ - $GAWK '{print $4}'` -LAST_EXTENT_LBA=`$HDPARM --fibmap $tmpfile | tail -1 | $GAWK '{print $2}'` - -## Verify the test string is in the extent read. -if ! dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$raiddev 2>/dev/null | $GREP "$TESTSTR" &>/dev/null ; then - echo "Test string was not found in last extent of tmpfile, as it should have been. Aborting." - do_cleanup 1 -fi - -## Now compare the mirror and the slaves to make sure they have the same data at the same LBA. -## -refchksum=`dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$raiddev 2>/dev/null | sha1sum` -index=0 -for slave in "${slaves[@]}" -do - chksum=`dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$slave 2>/dev/null | sha1sum` - - if [ "$chksum" != "$refchksum" ]; then - echo "Direct I/O of last extent of tmpfile on $slave doesn't match that of $raiddev. Excluding." - unset slaves[index] - fi - - let "index = $index + 1" -done -if [ "${slaves[0]}" = "" ]; then - echo "No constituent of $raiddev array has a matching checksum. Aborting." - do_cleanup 1 -fi - -echo "TRIMable constituents of $raiddev: ${slaves[@]}" - -## If they specified "--commit" on the command line, then prompt for confirmation first: -## -if [ "$commit" = "yes" ]; then - echo "Beginning TRIM operations..." -else - echo "This will be a DRY-RUN only. Use --commit to do it for real." - echo "Simulating TRIM operations..." -fi -get_trimlist="$HDPARM --fibmap $tmpfile" -[ $verbose -gt 0 ] && echo "get_trimlist=$get_trimlist" - - -## Begin gawk program -GAWKPROG=' - function append_range (lba,count ,this_count){ - nsectors += count; - while (count > 0) { - this_count = (count > 65535) ? 65535 : count - printf "%u:%u \n", lba, this_count - if (verbose > 1) - printf "%u:%u ", lba, this_count > "/dev/stderr" - lba += this_count - count -= this_count - nranges++; - } - } - { ## Output from "hdparm --fibmap", in absolute sectors: - if (NF == 4 && $2 ~ "^[1-9][0-9]*$") - append_range($2,$4) - next - } - END { - if (verbose > 1) - printf "\n" > "/dev/stderr" - if (err == 0 && commit != "yes") - printf "(dry-run) trimming %u sectors from %u ranges\n", nsectors, nranges > "/dev/stderr" - exit err - }' -## End gawk program - -## Run TRIM on each slave. Batch as requested. -sync -index=0 -for slave in "${slaves[@]}" -do - echo "TRIM beginning on $slave..." - - if [ "$commit" = "yes" ]; then - TRIM="$HDPARM --please-destroy-my-drive \ - --trim-sector-ranges-stdin /dev/$slave" - else - TRIM="$GAWK {}" - fi - - ## Different SSD's have a different maximum number of ranges they'll - ## accept in a single TRIM command. - if [ $max_ranges -eq 0 ] ; then - model=`$HDPARM -I /dev/$slave | $GAWK '/Model Number/ { print $NF }'` - case "$model" in - SSDSA[12]*) slave_max_range=512 ;; # Intel X18-M/X25-M - OCZ-VERTEX2) slave_max_range=64 ;; # OCZ Vertex2 - *) slave_max_range=65535 - esac - else - slave_max_range=$max_ranges - fi - [ $verbose -gt 0 ] && echo "$slave: max-ranges = $slave_max_range" - - $get_trimlist 2>/dev/null | $GAWK \ - -v commit="$commit" \ - -v verbose="$verbose" \ - "$GAWKPROG" | \ - if true; then - i=0 - while read range; do - (( i++ )) - if (( i <= $slave_max_range )); then - ranges=$ranges" "$range - else - [ $verbose -gt 0 ] && echo -e "Trim ranges:" $ranges - echo $ranges | $TRIM - ret=$? - if [ $ret -ne 0 ] ; then - do_cleanup $ret - fi - ranges=$range - i=1 - fi - done - [ $verbose -gt 0 ] && echo -e "Trim ranges:" $ranges - echo $ranges | $TRIM - ret=$? - if [ $ret -ne 0 ] ; then - do_cleanup $ret - fi - ranges="" - fi - - ret=$? - if [ $ret -ne 0 ] ; then - echo "TRIM failed on $slave. Aborting." - do_cleanup $ret - else - echo "TRIM finished successfully on $slave." - fi -done - -do_cleanup 0 - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/wiper/contrib/raid1ext4trim.sh-1.5 new/hdparm-9.42/wiper/contrib/raid1ext4trim.sh-1.5 --- old/hdparm-9.39/wiper/contrib/raid1ext4trim.sh-1.5 1970-01-01 01:00:00.000000000 +0100 +++ new/hdparm-9.42/wiper/contrib/raid1ext4trim.sh-1.5 2012-09-28 18:46:21.000000000 +0200 @@ -0,0 +1,407 @@ +#!/bin/bash +# +# SSD TRIM utility for live RAID1 mirrored ext4 drives. +# +# By Chris Caputo. Adapted from wiper.sh (ver 2.6) by Mark Lord. + +VERSION=1.5 + +# Copyright (C) 2010-2012 Chris Caputo. All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License Version 2, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +function usage_error(){ + echo "Usage:" + echo " ${0##*/} [--verbose] [--commit] [--reserve=#megs] [--max-ranges=#ranges] <raid_dev> <fsdir>" + echo "Examples:" + echo " ${0##*/} --verbose --commit --reserve=100 --max-ranges=512 md0 /" + echo " ${0##*/} --verbose --verbose md1 /boot" + echo + echo "Note: For best results, this script should be run on each ext4-based filesystem present on a RAID1 array." + echo + exit 1 +} + +echo "${0##*/}: TRIM utility for live RAID1 ext4 SATA SSDs, version $VERSION, by Chris Caputo, based on Mark Lord's wiper.sh." +echo + +## Parameter parsing for the main script. +## + +export verbose=0 +commit="" +reservemegs=0 +max_ranges=0 +argc=$# +raiddev="" +fsdir="" +while [ $argc -gt 0 ]; do + if [ "$1" = "--commit" ]; then + commit=yes + elif [ "$1" = "--verbose" ]; then + verbose=$((verbose + 1)) + elif [[ "$1" =~ --reserve= ]]; then + reservemegs=${1##--reserve=} + elif [[ "$1" =~ --max-ranges= ]]; then + max_ranges=${1##--max-ranges=} + elif [ "$1" = "" ]; then + usage_error + else + if [ "$raiddev" = "" ]; then + raiddev=${1##*/} + elif [ "$fsdir" = "" ]; then + fsdir=$1 + else + echo "$1: too many arguments, aborting." + exit 1 + fi + fi + argc=$((argc - 1)) + shift +done +[ "$raiddev" = "" ] && usage_error +[ "$fsdir" = "" ] && usage_error + +## Check --reserve number. +## + +isdigit () # Tests whether *entire string* is numerical. +{ # In other words, tests for integer variable. + [ $# -eq 1 ] || return 1 + + case $1 in + *[!0-9]*|"") return 1;; + *) return 0;; + esac +} + +if ! isdigit "$reservemegs" ; then + echo "'$reservemegs' is not numerical" + exit 1 +fi +if ! isdigit "$max_ranges" ; then + echo "'$max_ranges' is not numerical" + exit 1 +fi + +if [ $reservemegs -eq 0 ]; then + echo "Reserve defaulting to 10 megabytes." + reservemegs=10 +fi +reservekilos=$((reservemegs * 1024)) + +## Find a required program, or else give a nicer error message than we'd otherwise see: +## +function find_prog(){ + prog="$1" + if [ ! -x "$prog" ]; then + prog="${prog##*/}" + p=`type -f -P "$prog" 2>/dev/null` + if [ "$p" = "" ]; then + echo "$1: needed but not found, aborting." + exit 1 + fi + prog="$p" + [ $verbose -gt 0 ] && echo " --> using $prog instead of $1" + fi + echo "$prog" +} + +## Ensure we have most of the necessary utilities available before trying to proceed: +## +hash -r ## Refresh bash's cached PATH entries +HDPARM=`find_prog /sbin/hdparm` || exit 1 +GAWK=`find_prog /usr/bin/gawk` || exit 1 +GREP=`find_prog /bin/grep` || exit 1 +ID=`find_prog /usr/bin/id` || exit 1 +LS=`find_prog /bin/ls` || exit 1 +DF=`find_prog /bin/df` || exit 1 +RM=`find_prog /bin/rm` || exit 1 + +[ $verbose -gt 1 ] && HDPARM="$HDPARM --verbose" + +## I suppose this will confuse the three SELinux users out there: +## +if [ `$ID -u` -ne 0 ]; then + echo "Only the super-user can use this (try \"sudo $0\" instead), aborting." + exit 1 +fi + +## We need a very modern hdparm, for its --fallocate and --trim-sector-ranges-stdin flags: +## Version 9.25 added automatic determination of safe max-size of TRIM commands. +## +HDPVER=`$HDPARM -V | $GAWK '{gsub("[^0-9.]","",$2); if ($2 > 0) print ($2 * 100); else print 0; exit(0)}'` +if [ $HDPVER -lt 925 ]; then + echo "$HDPARM: version >= 9.25 is required, aborting." + exit 1 +fi + +## Check that this is a RAID1 device. +## +if ! $GREP raid1 /sys/block/$raiddev/md/level 1>/dev/null ; then + echo "$raiddev is not a RAID1 array." + exit 1 +fi + +## Get list of slave devices in the RAID1 mirror. +## +slaves=(`$LS /sys/block/$raiddev/slaves`) +#slaves=(sda sdb sdc) +#slaves=(md0) + +## Check for DEVTYPE disk and TRIM support on each slave. +## +index=0 +for slave in "${slaves[@]}" +do + # Check that slave is of DEVTYPE disk. + if ! $GREP "DEVTYPE=disk" /sys/block/$slave/uevent 1>/dev/null ; then + echo "$slave is not a whole disk. This program only works with full-disk RAID1, not RAID1 partitions." + exit 1 + fi + + # Check that slave has TRIM support. Exclude if not. + if ! $HDPARM -I /dev/$slave | $GREP -i '[ ][*][ ]*Data Set Management TRIM supported' &>/dev/null ; then + echo "$slave doesn't appear to support TRIM, per $HDPARM. Excluding." + unset slaves[index] + fi + + let "index = $index + 1" +done +if [ "${slaves[0]}" = "" ]; then + echo "No constituent of $raiddev array supports TRIM. Aborting." + exit 1 +fi + +## Check that fsdir is on an ext4 volume. +## +lines=`$DF --type=ext4 $fsdir 2>/dev/null | $GREP -v ^Filesystem | wc -l` +if [ $lines -ne 1 ]; then + echo "'$fsdir' does not appear to be on an ext4 filesystem. Aborting." + exit 1 +fi + +## Check that fsdir is a directory. +## +if [ ! -d $fsdir ]; then + echo "'$fsdir' is not a directory. Aborting." + exit 1 +fi + +## Check free space & calculate tmpfile size. +## +freesize=`$DF -P -B 1024 $fsdir | $GAWK '{r=$4}END{print r}'` +if [ "$freesize" = "" ]; then + echo "'$fsdir' is unknown to '$DF'. Aborting." + exit 1 +fi +if [ $freesize -lt $reservekilos ]; then + echo "'$fsdir' available space of $freesize KB is less than the $reservekilos KB to be reserved for the TRIM operation. Aborting." >&2 + exit 1 +fi +tmpsize=$((freesize - reservekilos)) +tmpfile="$fsdir/${0##*/}_TMPFILE.$$" + +## Clean up tmpfile (if any) and exit: +## +function do_cleanup(){ + if [ -e $tmpfile ]; then + echo "Removing temporary file '$tmpfile'..." + $RM -f $tmpfile + if [ -e $tmpfile ]; then + echo "Failed to remove '$tmpfile'!!!" + fi + fi + [ $1 -eq 0 ] && echo "Done." + [ $1 -eq 0 ] || echo "Aborted." >&2 + exit $1 +} + +## Prepare signal handling, in case we get interrupted while $tmpfile exists: +## +function do_abort(){ + echo + do_cleanup 1 +} +trap do_abort SIGTERM +trap do_abort SIGQUIT +trap do_abort SIGINT +trap do_abort SIGHUP +trap do_abort SIGPIPE + +## Do the fallocate. +## This is where we finally discover whether the filesystem actually +## supports --fallocate or not. Some folks will be disappointed here. +## +## Note that --fallocate does not actually write any file data to fsdev, +## but rather simply allocates formerly-free space to the tmpfile. +## +echo -n "Creating temporary file (${tmpsize} KB '$tmpfile') ... " +if ! $HDPARM --fallocate "${tmpsize}" $tmpfile ; then + echo "This kernel may not support 'fallocate'. Aborting." + exit 1 +fi +echo + +## Verify that slaves and RAID1 mirror have same base LBA. First add a test +## string to the tmpfile. "date" is used since it is ever changing. +## +TESTSTR=`date` +echo "$TESTSTR" >> $tmpfile +sync # this is critical +SECTOR_BYTES=`$HDPARM --fibmap $tmpfile | \ + $GREP "byte sectors" | \ + $GAWK '{print $9}'` +LAST_EXTENT_SECTOR_COUNT=`$HDPARM --fibmap $tmpfile | \ + tail -1 | \ + $GAWK '{print $4}'` +LAST_EXTENT_LBA=`$HDPARM --fibmap $tmpfile | tail -1 | $GAWK '{print $2}'` + +## Verify the test string is in the extent read. +if ! dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$raiddev 2>/dev/null | $GREP "$TESTSTR" &>/dev/null ; then + echo "Test string was not found in last extent of tmpfile, as it should have been. Aborting." + do_cleanup 1 +fi + +## Now compare the mirror and the slaves to make sure they have the same data at the same LBA. +## +refchksum=`dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$raiddev 2>/dev/null | sha1sum` +index=0 +for slave in "${slaves[@]}" +do + chksum=`dd iflag=direct status=noxfer bs=$SECTOR_BYTES count=$LAST_EXTENT_SECTOR_COUNT skip=$LAST_EXTENT_LBA if=/dev/$slave 2>/dev/null | sha1sum` + + if [ "$chksum" != "$refchksum" ]; then + echo "Direct I/O of last extent of tmpfile on $slave doesn't match that of $raiddev. Excluding." + unset slaves[index] + fi + + let "index = $index + 1" +done +if [ "${slaves[0]}" = "" ]; then + echo "No constituent of $raiddev array has a matching checksum. Aborting." + do_cleanup 1 +fi + +echo "TRIMable constituents of $raiddev: ${slaves[@]}" + +## If they specified "--commit" on the command line, then prompt for confirmation first: +## +if [ "$commit" = "yes" ]; then + echo "Beginning TRIM operations..." +else + echo "This will be a DRY-RUN only. Use --commit to do it for real." + echo "Simulating TRIM operations..." +fi +get_trimlist="$HDPARM --fibmap $tmpfile" +[ $verbose -gt 0 ] && echo "get_trimlist=$get_trimlist" + + +## Begin gawk program +GAWKPROG=' + function append_range (lba,count ,this_count){ + nsectors += count; + while (count > 0) { + this_count = (count > 65535) ? 65535 : count + printf "%u:%u \n", lba, this_count + if (verbose > 1) + printf "%u:%u ", lba, this_count > "/dev/stderr" + lba += this_count + count -= this_count + nranges++; + } + } + { ## Output from "hdparm --fibmap", in absolute sectors: + if (NF == 4 && $2 ~ "^[1-9][0-9]*$") + append_range($2,$4) + next + } + END { + if (verbose > 1) + printf "\n" > "/dev/stderr" + if (err == 0 && commit != "yes") + printf "(dry-run) trimming %u sectors from %u ranges\n", nsectors, nranges > "/dev/stderr" + exit err + }' +## End gawk program + +## Run TRIM on each slave. Batch as requested. +sync +index=0 +for slave in "${slaves[@]}" +do + echo "TRIM beginning on $slave..." + + if [ "$commit" = "yes" ]; then + TRIM="$HDPARM --please-destroy-my-drive \ + --trim-sector-ranges-stdin /dev/$slave" + else + TRIM="$GAWK {}" + fi + + ## Different SSD's have a different maximum number of ranges they'll + ## accept in a single TRIM command. + if [ $max_ranges -eq 0 ] ; then + model=`$HDPARM -I /dev/$slave | $GAWK '/Model Number/ { print $NF }'` + case "$model" in + SSDSA[12]*) slave_max_range=512 ;; # Intel X18-M/X25-M + OCZ-VERTEX2) slave_max_range=64 ;; # OCZ Vertex2 + *) slave_max_range=65535 + esac + else + slave_max_range=$max_ranges + fi + [ $verbose -gt 0 ] && echo "$slave: max-ranges = $slave_max_range" + + $get_trimlist 2>/dev/null | $GAWK \ + -v commit="$commit" \ + -v verbose="$verbose" \ + "$GAWKPROG" | \ + if true; then + i=0 + while read range; do + (( i++ )) + if (( i <= $slave_max_range )); then + ranges=$ranges" "$range + else + [ $verbose -gt 0 ] && echo -e "Trim ranges:" $ranges + echo $ranges | $TRIM + ret=$? + if [ $ret -ne 0 ] ; then + do_cleanup $ret + fi + ranges=$range + i=1 + fi + done + [ $verbose -gt 0 ] && echo -e "Trim ranges:" $ranges + echo $ranges | $TRIM + ret=$? + if [ $ret -ne 0 ] ; then + do_cleanup $ret + fi + ranges="" + fi + + ret=$? + if [ $ret -ne 0 ] ; then + echo "TRIM failed on $slave. Aborting." + do_cleanup $ret + else + echo "TRIM finished successfully on $slave." + fi +done + +do_cleanup 0 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.39/wiper/wiper.sh new/hdparm-9.42/wiper/wiper.sh --- old/hdparm-9.39/wiper/wiper.sh 2011-02-21 15:58:26.000000000 +0100 +++ new/hdparm-9.42/wiper/wiper.sh 2012-09-28 20:08:37.000000000 +0200 @@ -2,7 +2,7 @@ # # SATA SSD free-space TRIM utility, by Mark Lord <[email protected]> -VERSION=3.4 +VERSION=3.5 # Copyright (C) 2009-2010 Mark Lord. All rights reserved. # @@ -252,6 +252,11 @@ ## because that's the pattern such systems also use in /proc/mounts. ## Later, at time of use, we'll try harder to find the real rootdev. ## +## FIXME: apparently this doesn't work on SuSE Linux, though. +## So for there, we'll likely need to read /etc/mtab, +## or be a lot more clever and get it somehow from statfs or something. +## FIXME: or use target from /dev/root symlink for Gentoo as well. +## function match_rootdev() { rdev="" rdevno="$1" @@ -793,7 +798,7 @@ blksects = $NF / 512 next } - /^Group [1-9][0-9]*:/ { ## Second stage output from dumpe2fs: + /^Group [0-9][0-9]*:/ { ## Second stage output from dumpe2fs: in_groups = 1 next } -- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
