Hello community,
here is the log from the commit of package hdparm for openSUSE:Factory
checked in at Fri Jul 23 21:46:49 CEST 2010.
--------
--- hdparm/hdparm.changes 2010-03-10 12:50:00.000000000 +0100
+++ hdparm/hdparm.changes 2010-07-22 13:13:38.000000000 +0200
@@ -1,0 +2,17 @@
+Thu Jul 22 11:11:55 UTC 2010 - puzel@novell.com
+
+- update to hdparm-9.29
+ * add --offset for use with -t, to get timings from middle/end
+ of drive,
+ * restrict --trim-sector-ranges-stdin to small TRIM commands on
+ most drives
+ * fix w62 bug in -I
+ * dump all data bytes with --verbose
+ * warn about bad/missing sense data, but continue regardless
+ * show in/out data[] separately with --verbose
+ * Add reporting to -I for sata3 signaling speed.
+ * force use of ATA_16 for all commands to ATAPI devices.
+ * supply a sector count of "1" for IDENTIFY commands, to
+ satisfy buggy USB3 bridges.
+
+-------------------------------------------------------------------
calling whatdependson for head-i586
Old:
----
hdparm-9.28.tar.bz2
New:
----
hdparm-9.29.tar.bz2
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ hdparm.spec ++++++
--- /var/tmp/diff_new_pack.WnkEkw/_old 2010-07-23 21:42:40.000000000 +0200
+++ /var/tmp/diff_new_pack.WnkEkw/_new 2010-07-23 21:42:40.000000000 +0200
@@ -1,5 +1,5 @@
#
-# spec file for package hdparm (Version 9.28)
+# spec file for package hdparm (Version 9.29)
#
# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany.
#
@@ -24,16 +24,16 @@
PreReq: %insserv_prereq %fillup_prereq coreutils
Provides: base:/sbin/hdparm
AutoReqProv: on
-Version: 9.28
+Version: 9.29
Release: 1
-Summary: A Program to Get and Set Hard Disk Parameters
+Summary: A Program to get and set hard disk parameters
Source: %{name}-%{version}.tar.bz2
Source1: 56-idedma.rules
Source2: sysconfig.ide
Source3: udev.idedma.sh
-Patch1: %{name}-nostrip.patch
-Patch2: %{name}-wiper-warn.patch
-Patch3: %{name}-leak-fix.patch
+Patch1: hdparm-nostrip.patch
+Patch2: hdparm-wiper-warn.patch
+Patch3: hdparm-leak-fix.patch
Url: http://sourceforge.net/projects/hdparm/
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -42,7 +42,6 @@
driver and IDE drives.
-
Authors:
--------
Mark Lord
++++++ hdparm-9.28.tar.bz2 -> hdparm-9.29.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/Changelog new/hdparm-9.29/Changelog
--- old/hdparm-9.28/Changelog 2010-03-09 15:17:20.000000000 +0100
+++ new/hdparm-9.29/Changelog 2010-06-30 21:15:27.000000000 +0200
@@ -1,3 +1,14 @@
+hdparm-9.29
+ - add --offset for use with -t, to get timings from middle/end of drive,
+ courtesy of Sergei Kirjanov
+ - restrict --trim-sector-ranges-stdin to small TRIM commands on most drives
+ - fix w62 bug in -I
+ - dump all data bytes with --verbose
+ - warn about bad/missing sense data, but continue regardless
+ - show in/out data[] separately with --verbose
+ - Add reporting to -I for sata3 signaling speed.
+ - force use of ATA_16 for all commands to ATAPI devices.
+ - supply a sector count of "1" for IDENTIFY commands, to satisfy buggy USB3 bridges.
hdparm-9.28
- check for EBADE for IDE/ATAPI compatibility with recent kernels
- always issue both methods when setting DVD speed with -E
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/hdparm.8 new/hdparm-9.29/hdparm.8
--- old/hdparm-9.28/hdparm.8 2010-03-09 15:18:48.000000000 +0100
+++ new/hdparm-9.29/hdparm.8 2010-06-30 21:15:51.000000000 +0200
@@ -1,4 +1,4 @@
-.TH HDPARM 8 "March 2010" "Version 9.28"
+.TH HDPARM 8 "June 2010" "Version 9.29"
.SH NAME
hdparm \- get/set SATA/IDE device parameters
@@ -449,6 +449,14 @@
Get or set the "ignore write errors" flag in the driver.
Do NOT play with this without grokking the driver source code first.
.TP
+.I --offset
+Offsets to given number of GiB (1024*1024*1024) when performing
+.B -t
+timings of device reads.
+Speed changes (about twice) along many mechanical drives.
+Usually the maximum is at the beginning, but not always.
+Solid-state drives (SSDs) should show similar timings regardless of offset.
+.TP
.I -p
Attempt to reprogram the IDE interface chipset for the specified PIO mode,
or attempt to auto-tune for the "best" PIO mode supported by the drive.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/hdparm.c new/hdparm-9.29/hdparm.c
--- old/hdparm-9.28/hdparm.c 2010-03-09 15:18:33.000000000 +0100
+++ new/hdparm-9.29/hdparm.c 2010-06-30 21:15:34.000000000 +0200
@@ -1,5 +1,6 @@
/* hdparm.c - Command line interface to get/set hard disk parameters */
/* - by Mark Lord (C) 1994-2008 -- freely distributable */
+#define _LARGEFILE64_SOURCE /*for lseek64*/
#define _BSD_SOURCE /* for strtoll() */
#include
#include
@@ -34,7 +35,7 @@
extern const char *minor_str[];
-#define VERSION "v9.28"
+#define VERSION "v9.29"
#ifndef O_DIRECT
#define O_DIRECT 040000 /* direct disk access, not easily obtained from headers */
@@ -64,6 +65,8 @@
static int do_flush_wcache = 0;
//static int set_wdidle3 = 0;
+static int set_timings_offset = 0;
+static __u64 timings_offset = 0;
static int set_fsreadahead= 0, get_fsreadahead= 0, fsreadahead= 0;
static int set_readonly = 0, get_readonly = 0, readonly = 0;
static int set_unmask = 0, get_unmask = 0, unmask = 0;
@@ -334,9 +337,18 @@
if (err)
goto quit;
- printf(" Timing %s disk reads: ", (open_flags & O_DIRECT) ? "O_DIRECT" : "buffered");
+ printf(" Timing %s disk reads", (open_flags & O_DIRECT) ? "O_DIRECT" : "buffered");
+ if (set_timings_offset)
+ printf(" (offset %llu GB)", timings_offset / 0x40000000ULL);
+ printf(": ");
fflush(stdout);
+ if (set_timings_offset && lseek64(fd, timings_offset, SEEK_SET) == (off64_t)-1) {
+ err = errno;
+ perror("lseek() failed");
+ goto quit;
+ }
+
/*
* getitimer() is used rather than gettimeofday() because
* it is much more consistent (on my machine, at least).
@@ -819,13 +831,14 @@
memset(args, 0, sizeof(args));
last_identify_op = ATA_OP_IDENTIFY;
args[0] = last_identify_op;
- args[3] = 1;
+ args[3] = 1; /* sector count */
if (do_drive_cmd(fd, args)) {
+ prefer_ata12 = 0;
last_identify_op = ATA_OP_PIDENTIFY;
args[0] = last_identify_op;
args[1] = 0;
args[2] = 0;
- args[3] = 1;
+ args[3] = 1; /* sector count */
if (do_drive_cmd(fd, args)) {
perror(" HDIO_DRIVE_CMD(identify) failed");
return NULL;
@@ -1193,22 +1206,59 @@
exit(err);
}
+static void
+extract_id_string (__u16 *idw, int words, char *dst)
+{
+ char *e;
+ int i, max = words * 2;
+
+ for (i = 0; i < words; ++i) {
+ __u16 w = idw[i];
+ w = (__u16)(__be16)(w);
+ dst[i*2 ] = w >> 8;
+ dst[i*2+1] = w;
+ }
+ dst[max] = '\0';
+ for (e = dst + max; --e != dst;) {
+ if (*e && *e != ' ')
+ break;
+ *e = '\0';
+ }
+}
+
+static int
+get_trim_dev_limit (void *id)
+{
+ __u16 *idw = id;
+ char model[41];
+
+ extract_id_string(idw + 27, 20, model);
+ if (0 == strcmp(model, "OCZ VERTEX-LE"))
+ return 8;
+ if (0 == strcmp(model, "OCZ-VERTEX"))
+ return 64;
+ return 1; /* all other drives, including Intel SSDs */
+}
+
static int
do_trim_from_stdin (int fd, const char *devname, void *id)
{
__u64 *data, range, nsectors = 0, lba_limit;
unsigned int max_kb, data_sects, data_bytes;
- unsigned int total_ranges = 0, nranges = 0, max_ranges;
+ unsigned int total_ranges = 0, nranges = 0, max_ranges, dev_limit;
int err = 0;
id = get_identify_data(fd, id);
lba_limit = id ? get_lba_capacity(id) : (1ULL << 48) - 1;
+ dev_limit = get_trim_dev_limit(id);
err = sysfs_get_attr(fd, "queue/max_sectors_kb", "%u", &max_kb, NULL, 0);
if (err || max_kb == 0)
- data_sects = 128; /* "safe" default for most hardware */
+ data_sects = 128; /* "safe" default for most controllers */
else
data_sects = max_kb * 2;
+ if (data_sects > dev_limit)
+ data_sects = dev_limit;
data_bytes = data_sects * 512;
data = mmap(NULL, data_bytes, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
@@ -1217,6 +1267,7 @@
perror("mmap(MAP_ANONYMOUS)");
exit(err);
}
+ memset(data, 0, data_bytes);
max_ranges = data_bytes / sizeof(range);
do {
@@ -1240,6 +1291,7 @@
data[nranges++] = __cpu_to_le64(range);
if (nranges == max_ranges) {
err = trim_sectors(fd, devname, nranges, data, nsectors);
+ memset(data, 0, data_bytes);
nranges = 0;
nsectors = 0;
}
@@ -1426,6 +1478,7 @@
" --Istdin Read identify data from stdin as ASCII hex\n"
" --Istdout Write identify data to stdout as ASCII hex\n"
" --make-bad-sector Deliberately corrupt a sector directly on the media (VERY DANGEROUS)\n"
+ " --offset use with -t, to begin timings at given offset (in GiB) from start of drive\n"
" --prefer-ata12 Use 12-byte (instead of 16-byte) SAT commands when possible\n"
" --read-sector Read and dump (in hex) a sector directly from the media\n"
" --security-help Display help for ATA security commands\n"
@@ -2497,6 +2550,10 @@
} else if (0 == strcasecmp(name, "prefer-ata12")) {
prefer_ata12 = 1;
--num_flags_processed; /* doesn't count as an action flag */
+ } else if (0 == strcasecmp(name, "offset")) {
+ set_timings_offset = 1;
+ get_u64_parm(0, 0, NULL, &timings_offset, 0, ~0, name, "GB offset for -t flag");
+ timings_offset *= 0x40000000ULL;
} else if (0 == strcasecmp(name, "yes-i-know-what-i-am-doing")) {
i_know_what_i_am_doing = 1;
--num_flags_processed; /* doesn't count as an action flag */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/hdparm.lsm new/hdparm-9.29/hdparm.lsm
--- old/hdparm-9.28/hdparm.lsm 2010-03-09 15:21:19.000000000 +0100
+++ new/hdparm-9.29/hdparm.lsm 2010-06-30 21:25:11.000000000 +0200
@@ -1,9 +1,10 @@
Begin4
Title: hdparm
-Version: 9.28
-Entered-date: 2010-03-09
+Version: 9.29
+Entered-date: 2010-06-30
Description: hdparm - get/set hard disk parameters for Linux SATA/IDE drives.
- v9.28 Assorted fixes, updated wiper.sh to v2.8
+ v9.29 Assorted fixes, updated wiper.sh, made trim compatible with many more SSDs
+ v9.28 Assorted fixes, updated wiper.sh
v9.27 Fix compatibility with old IDE drivers; was broken for many versions now
v9.26 Fix old -i model-name bug; fixed --security-erase-enhanced; other fixes
v9.25 Limit --trim-sector-ranges-stdin to max_sectors_kb per TRIM command
@@ -102,7 +103,7 @@
Maintained-by: mlord@pobox.com (Mark Lord)
Primary-site: http://sourceforge.net/projects/hdparm/
Alternate-site: http://www.ibiblio.org/pub/Linux/system/hardware
- 114K hdparm-9.28.tar.gz
+ 117K hdparm-9.29.tar.gz
4K hdparm.lsm
Platforms: Linux, kernels 2.2 through 2.6
Copying-policy: BSD License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/identify.c new/hdparm-9.29/identify.c
--- old/hdparm-9.28/identify.c 2010-01-24 07:15:46.000000000 +0100
+++ new/hdparm-9.29/identify.c 2010-06-29 22:43:02.000000000 +0200
@@ -433,7 +433,7 @@
"unknown 76[6]", /* word 76 bit 6 */
"unknown 76[5]", /* word 76 bit 5 */
"unknown 76[4]", /* word 76 bit 4 */
- "unknown 76[3]", /* word 76 bit 3 */
+ "Gen3 signaling speed (6.0Gb/s)", /* word 76 bit 3 */
"Gen2 signaling speed (3.0Gb/s)", /* word 76 bit 2 */
"Gen1 signaling speed (1.5Gb/s)", /* word 76 bit 1 */
"unknown 76[0]" /* word 76 bit 0 */
@@ -1101,7 +1101,8 @@
sdma_ok = 0; /* word 62 has been re-purposed for non-sdma mode reporting */
printf("\tDMADIR bit required in PACKET commands\n");
} else {
- __u8 w62 = val[62], hi = w62 >> 8, lo = w62;
+ __u16 w62 = val[62];
+ __u8 hi = w62 >> 8, lo = w62;
if (!w62 || (lo & 0xf8))
sdma_ok = 0;
else if (hi && hi != 1 && hi != 2 && hi != 4)
@@ -1330,7 +1331,8 @@
printf("\n");
}
}
- if((eqpt != CDROM) && (like_std > 3) && (val[CMDS_EN_2] & WWN_SUP)) {
+ //printf("w84=0x%04x w87=0x%04x like_std=%d\n", val[84], val[87], like_std);
+ if((eqpt != CDROM) && (like_std > 3) && (val[CMDS_SUPP_2] & WWN_SUP)) {
printf("Logical Unit WWN Device Identifier: %04x%04x%04x%04x\n", val[108], val[109], val[110], val[111]);
printf("\tNAA\t\t: %x\n", (val[108] & 0xf000) >> 12);
printf("\tIEEE OUI\t: %06x\n", (((val[108] & 0x0fff) << 12) | ((val[109] & 0xfff0) >> 4)));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/sgio.c new/hdparm-9.29/sgio.c
--- old/hdparm-9.28/sgio.c 2010-02-13 21:38:38.000000000 +0100
+++ new/hdparm-9.29/sgio.c 2010-05-12 15:35:22.000000000 +0200
@@ -162,10 +162,16 @@
unsigned char cdb[SG_ATA_16_LEN];
unsigned char sb[32], *desc;
struct scsi_sg_io_hdr io_hdr;
+ int prefer12 = prefer_ata12;
+
+ if (tf->command == ATA_OP_PIDENTIFY)
+ prefer12 = 0;
memset(&cdb, 0, sizeof(cdb));
memset(&sb, 0, sizeof(sb));
memset(&io_hdr, 0, sizeof(struct scsi_sg_io_hdr));
+ if (data && data_bytes && !rw)
+ memset(data, 0, data_bytes);
if (dma) {
//cdb[1] = data ? (rw ? SG_ATA_PROTO_UDMA_OUT : SG_ATA_PROTO_UDMA_IN) : SG_ATA_PROTO_NON_DATA;
@@ -179,7 +185,7 @@
cdb[2] |= rw ? SG_CDB2_TDIR_TO_DEV : SG_CDB2_TDIR_FROM_DEV;
}
- if (!prefer_ata12 || tf->is_lba48) {
+ if (!prefer12 || tf->is_lba48) {
cdb[ 0] = SG_ATA_16;
cdb[ 4] = tf->lob.feat;
cdb[ 6] = tf->lob.nsect;
@@ -221,8 +227,8 @@
if (verbose) {
dump_bytes("outgoing cdb", cdb, sizeof(cdb));
- if (data)
- dump_bytes("data", data, 16);
+ if (rw && data)
+ dump_bytes("outgoing_data", data, data_bytes);
}
if (ioctl(fd, SG_IO, &io_hdr) == -1) {
@@ -235,28 +241,48 @@
fprintf(stderr, "SG_IO: ATA_%u status=0x%x, host_status=0x%x, driver_status=0x%x\n",
io_hdr.cmd_len, io_hdr.status, io_hdr.host_status, io_hdr.driver_status);
- if (io_hdr.host_status || io_hdr.driver_status != SG_DRIVER_SENSE
- || (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION))
- {
+ if (io_hdr.status && io_hdr.status != SG_CHECK_CONDITION) {
+ if (verbose)
+ fprintf(stderr, "SG_IO: bad status: 0x%x\n", io_hdr.status);
+ errno = EBADE;
+ return -1;
+ }
+ if (io_hdr.host_status) {
if (verbose)
- fprintf(stderr, "SG_IO: bad response (not CHECK_CONDITION)\n");
+ fprintf(stderr, "SG_IO: bad host status: 0x%x\n", io_hdr.host_status);
errno = EBADE;
return -1;
}
+ if (verbose) {
+ dump_bytes("SG_IO: sb[]", sb, sizeof(sb));
+ if (!rw && data)
+ dump_bytes("incoming_data", data, data_bytes);
+ }
- desc = sb + 8;
- if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) {
+ if (io_hdr.driver_status && (io_hdr.driver_status != SG_DRIVER_SENSE)) {
if (verbose)
- dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb));
- errno = EBADE;
+ fprintf(stderr, "SG_IO: bad driver status: 0x%x\n", io_hdr.driver_status);
+ errno = EBADE;
return -1;
}
- if (verbose)
- dump_bytes("SG_IO: sb[]", sb, sizeof(sb));
+ desc = sb + 8;
+ if (io_hdr.driver_status != SG_DRIVER_SENSE) {
+ if (sb[0] | sb[1] | sb[2] | sb[3] | sb[4] | sb[5] | sb[6] | sb[7] | sb[8] | sb[9]) {
+ static int second_try = 0;
+ if (!second_try++)
+ fprintf(stderr, "SG_IO: questionable sense data, results may be incorrect\n");
+ } else {
+ static int second_try = 0;
+ if (!second_try++)
+ fprintf(stderr, "SG_IO: missing sense data, results may be incorrect\n");
+ }
+ } else if (sb[0] != 0x72 || sb[7] < 14 || desc[0] != 0x09 || desc[1] < 0x0c) {
+ dump_bytes("SG_IO: bad/missing sense data, sb[]", sb, sizeof(sb));
+ }
if (verbose) {
- int len = desc[1], maxlen = sizeof(sb) - 8 - 2;
+ unsigned int len = desc[1], maxlen = sizeof(sb) - 8 - 2;
if (len > maxlen)
len = maxlen;
dump_bytes("SG_IO: desc[]", desc, len);
@@ -320,8 +346,8 @@
}
tf_init(&tf, args[0], 0, args[1]);
tf.lob.feat = args[2];
+ tf.lob.nsect = args[3];
if (tf.command == ATA_OP_SMART) {
- tf.lob.nsect = args[3];
tf.lob.lbal = args[1];
tf.lob.lbam = 0x4f;
tf.lob.lbah = 0xc2;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/wiper/README.txt new/hdparm-9.29/wiper/README.txt
--- old/hdparm-9.28/wiper/README.txt 2009-10-02 15:14:32.000000000 +0200
+++ new/hdparm-9.29/wiper/README.txt 2010-06-30 21:19:58.000000000 +0200
@@ -1,4 +1,4 @@
-TRIM / wiper script for SATA SSDs (October 2009)
+TRIM / wiper script for SATA SSDs (June 2010)
=================================================
The wiper.sh script is for tuning up SATA SSDs (Solid-State-Drives).
@@ -16,13 +16,7 @@
Please back-up your data to a *different* physical drive before trying it.
And if you are at all worried, then DO NOT USE THIS SCRIPT!!
-Once there are drives in the marketplace with production firmware that supports
-the SATA DSM TRIM command, then this will get tested a bit more over time.
-As that happens, it will be moved out of this directory and installed alongside
-the hdparm executable, probably under /sbin or /usr/sbin.
-
-Until then, DO NOT USE THIS SCRIPT if you cannot afford losing your data!!
-
+DO NOT USE THIS SCRIPT if you cannot afford losing your data!!
This script works for read-write mounted ext4 and xfs filesystems,
and for read-only mounted/unmounted ext2, ext3, ext4, reiser3 and xfs filesystems.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/wiper/contrib/README.contrib new/hdparm-9.29/wiper/contrib/README.contrib
--- old/hdparm-9.28/wiper/contrib/README.contrib 1970-01-01 01:00:00.000000000 +0100
+++ new/hdparm-9.29/wiper/contrib/README.contrib 2010-06-30 21:24:27.000000000 +0200
@@ -0,0 +1,7 @@
+Contributed scripts and notes from others (untested by me).
+===========================================================
+
+raid1ext4trim.sh-1.2
+ Similar to wiper.sh, but for ext4/RAID1 mirrors.
+ By Chris Caputo. Adapted from wiper.sh (ver 2.6) by Mark Lord.
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hdparm-9.28/wiper/contrib/raid1ext4trim.sh-1.2 new/hdparm-9.29/wiper/contrib/raid1ext4trim.sh-1.2
--- old/hdparm-9.28/wiper/contrib/raid1ext4trim.sh-1.2 1970-01-01 01:00:00.000000000 +0100
+++ new/hdparm-9.29/wiper/contrib/raid1ext4trim.sh-1.2 2010-06-30 21:21:42.000000000 +0200
@@ -0,0 +1,403 @@
+#!/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.2
+
+# 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] <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..."
+ $RM -f $tmpfile
+ 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
+
+## 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) ... "
+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
+ exit $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
+ exit $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.28/wiper/wiper.sh new/hdparm-9.29/wiper/wiper.sh
--- old/hdparm-9.28/wiper/wiper.sh 2010-03-09 15:17:37.000000000 +0100
+++ new/hdparm-9.29/wiper/wiper.sh 2010-06-30 21:16:12.000000000 +0200
@@ -2,9 +2,9 @@
#
# SATA SSD free-space TRIM utility, by Mark Lord
-VERSION=2.6
+VERSION=2.7
-# Copyright (C) 2009 Mark Lord. All rights reserved.
+# Copyright (C) 2009-2010 Mark Lord. All rights reserved.
#
# Requires gawk, a really-recent hdparm, and various other programs.
# This needs to be redone entirely in C, for 64-bit math, someday.
@@ -21,6 +21,10 @@
# 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
+#
+# Note for OCZ Vertex-LE users: the drive firmware will error when
+# attempting to trim the final sector of the drive. To avoid this,
+# partition the drive such that the final sector is not used.
export LANG=C
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
--
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org