From: Tejun Heo <htejun@gmail.com>
To: Bruce Allen <ballen@gravity.phys.uwm.edu>
Cc: roland.kletzing@materna.de,
Smartmontools Developers List
<smartmontools-devel@lists.sourceforge.net>,
IDE/ATA development list <linux-ide@vger.kernel.org>,
Jeff Garzik <jeff@garzik.org>, Mark Lord <liml@rtr.ca>,
Alan Cox <alan@lxorguk.ukuu.org.uk>,
scott@ubuntu.com
Subject: Re: regarding crazy head unloads
Date: Fri, 23 May 2008 20:36:54 +0900 [thread overview]
Message-ID: <4836AC56.2010501@gmail.com> (raw)
In-Reply-To: <48361F88.7040400@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 173 bytes --]
Here's updated version which can do glob matching and other stuff. I've
also set up a git tree.
http://git.kernel.org/?p=linux/kernel/git/tj/storage-fixup.git
--
tejun
[-- Attachment #2: storage-fixup --]
[-- Type: text/plain, Size: 7392 bytes --]
#! /bin/bash
#
# storage-fixup - Tejun Heo <teheo@suse.de>
#
# Script to issue fix up commands for weird disks. This is primarily
# to adjust ATA APM setting. Some laptop BIOSen set this value too
# aggressively causing frequent head unloads which can kill the drive
# quickly. This script should be called during boot and resume. It
# examines rules from /etc/stroage-fixup.conf and executes matching
# commands.
#
# In stroage-fixup.conf, empty lines and lines starting w/ # are
# ignored. Each line starts with rule, dmi, hal or act.
#
# rule RULENAME
# Starts a rule. $RULENAME can't contain whitespaces.
#
# dmi KEY PATTERN
# Checks whether DMI value for KEY matches PATTERN. If not, the
# rule is skipped.
#
# hal KEY PATTERN
# Checks whether there are devices which has KEY value matching
# PATTERN. storage-fixup determines applies actions to devices
# which match all hal matches, so all rules should have at least
# one hal match.
#
# act ACTION
# Executes ACTION on matched devices. ACTION can contain $DEV
# which will be substituted with device file of matching device.
#
# PATTERN is bash glob pattern.
#
# For example, the following (useless) rule disables APM on the first
# harddrive of my machine.
#
# rule p5w64
# dmi baseboard-product-name P5W64 WS Pro
# dmi baseboard-manufacturer ASUSTeK Computer INC.
# hal storage.model WDC WD5000YS-01M
# hal storage.serial *-01_WD-WMANU1217262
# act hdparm -B 255 $DEV
#
declare usage="
Usage: storage-fixup [-h] [-V] [-v] [-b] [-c config_file]
-h Print this help message and exit
-V Print version and exit
-v Verbose
-d Dry run, don't actually execute action
-c Use config_file instead of /etc/storage-fixup.conf
"
declare hal_find_by_capability=${HAL_FIND_BY_CAPABILITY:-hal-find-by-capability}
declare hal_get_property=${HAL_GET_PROPERTY:-hal-get-property}
declare dmidecode=${DMIDECODE:-dmidecode}
declare version=0.1
declare conf_file=/etc/storage-fixup.conf
declare newline=$'\n'
declare dry_run=0 verbose=0 lineno=0 skip=0 rule_name="" reply
declare -a storage_ids
declare -a hal_cache
declare -a matches
log() {
echo "storage-fixup: $@"
}
warn() {
log "$@" 1>&2
}
debug() {
if [ $verbose -ne 0 ]; then
warn "$@"
fi
}
#
# do_dmi - perform DMI match
# @key: DMI key to be passed as --string argument to dmidecode
# @pattern: glob pattern to match
#
# Returns 0 on match, 1 on mismatch, 2 on invalid match (triggers
# warning).
#
do_dmi() {
local key="$1" pattern="$2"
local val
if [ -z "$key" -o -z "$pattern" ]; then
return 1
fi
val=$($dmidecode --string "$key")
if [ "$?" -ne 0 ]; then
return 2
fi
if [ -z "${val##$pattern}" ]; then
debug "Y $lineno $rule_name dmi $key=$pattern"
return 0
fi
debug "N $lineno $rule_name dmi $key=$pattern"
return 1
}
#
# search_hal_cache - search hal cache
# @id: udi of the device to search for
# @key: key of hal property to search
#
# Searches hal cache and returns 0 if found, 1 if @key properties are
# cached but matching entry is not found, 2 if @key properties are not
# cached yet. On success, the matched property is returned in $reply.
#
search_hal_cache() {
local id="$1" key="$2"
local i key_found=0 cache len match
reply=
for ((i=0;i<${#hal_cache[@]};i++)); do
cache=${hal_cache[i]}
len=${#cache}
match="${cache#$key }"
if [ ${#match} -ne $len ]; then
key_found=1
elif [ $key_found -eq 1 ]; then
return 1
fi
match="${cache#$key $id }"
if [ ${#match} -ne $len ]; then
reply="$match"
return 0
fi
done
if [ $key_found -eq 1 ]; then
return 1
else
return 2
fi
}
#
# fetch_hal_property - fetch hal property matching id and key
# @id: udi of the device to fetch property for
# @key: key of the property to fetch
#
# Fetch @key property for udi @id. If @key properties are already
# cached, it's returned from cache. If not, cache is populated with
# @key properties and searched again.
#
# Returns 0 if found, 1 if not found, 2 if something went wrong. On
# success, the matched property is returned in $reply.
#
fetch_hal_property() {
local id="$1" key="$2" property
local i ret tid cnt=0
# search cache
search_hal_cache "$id" "$key"
ret=$?
if [ $ret -ne 2 ]; then
return $ret
fi
# $key wasn't in the cache, populate the cache
# placeholder indicating $key has been populated
hal_cache+=("$key ")
# run hal-get-property on each storage device and put the result in cache
for ((i=0;i<${#storage_ids[@]};i++)); do
tid="${storage_ids[i]}"
property="$($hal_get_property --udi "$tid" --key "$key")"
if [ -n "$property" ]; then
hal_cache+=("$key $tid $property")
true $((cnt++))
fi
done
debug "C $cnt entries added to hal cache for $key"
# and retry
search_hal_cache "$id" "$key"
return $?
}
#
# do_hal - perform HAL match
# @key: property key of interest
# @pattern: pattern to match
#
# Walk through $matches array and match each id against @key and
# @pattern. Entries which don't match are removed from $matches.
#
# Returns 0 if $matches contain any entry after matching, 1 if it's
# empty, 2 if something went wrong.
#
do_hal() {
local key="$1" pattern="$2" property i
local -a old_matches=("${matches[@]}")
if [ -z "$1" -o -z "$2" ]; then
return 2
fi
matches=()
for ((i=0;i<${#old_matches[@]};i++)); do
fetch_hal_property "${old_matches[i]}" "$key"
if [ $? -eq 0 -a -z "${reply##$pattern}" ]; then
matches+=("${old_matches[i]}")
fi
done
if [ ${#matches[@]} -eq 0 ]; then
debug "N $lineno $rule_name hal $1=$2"
return 1
fi
debug "Y $lineno $rule_name hal nr_devs=${#matches[@]} $1=$2"
return 0
}
#
# do_act - execute action
# @act: action to execute
#
# Execute @act for each device in $matches. "$DEV" in @act is
# substituted with the /dev node of each match. If $dry_run is set,
# the action is logged but not actually executed.
#
# Returns 0.
#
do_act() {
local act="$1"
local id dev
for id in "${matches[@]}"; do
if ! DEV=$($hal_get_property --udi "$id" --key block.device); then
warn "can't find device node for $id"
continue
fi
if [ $dry_run -eq 0 ]; then
eval log "$rule_name: executing \"$act\""
eval "$1"
else
eval log "$rule_name: dry-run \"$act\""
fi
done
return 0
}
#
# Execution starts here
#
while getopts "dvVc:h" option; do
case $option in
d)
dry_run=1;;
v)
verbose=1;;
V)
echo "$version"
exit 0;;
c)
conf_file=$OPTARG;;
*)
echo "$usage" 2>&1
exit 1;;
esac
done
storage_ids=($($hal_find_by_capability --capability storage))
debug "I ${#storage_ids[@]} storage devices"
while read f0 f1 f2; do
true $((lineno++))
if [ -z ${f0###*} ]; then
continue
fi
if [ "$f0" = rule ]; then
rule_name=$f1
skip=0
matches=("${storage_ids[@]}")
continue
fi
if [ $skip -ne 0 ]; then
continue
fi
case "$f0" in
dmi)
do_dmi "$f1" "$f2"
;;
hal)
do_hal "$f1" "$f2"
;;
act)
do_act "$f1 $f2"
;;
*)
false
;;
esac
ret=$?
if [ $ret -ne 0 ]; then
if [ $ret -eq 2 ]; then
warn "malformed line $lineno \"$f0 $f1 $f2\","\
"skipping rule $rule_name" 2>&1
fi
skip=1
fi
done < $conf_file
[-- Attachment #3: storage-fixup.conf --]
[-- Type: text/plain, Size: 1351 bytes --]
#
# /etc/storage-fixup.conf - Configuration file for storage-fixup
#
# Blank lines and lines starting with # are ignored. Please read
# comment at the top of storage-fixup for more information.
#
# Drive model patterns are generalized to cover drives from the same
# family. Drive manufacturers usually have datasheets or web pages
# listing all models of the same family.
#
# The DMI part is difficult to generalize as there's no such
# information. We'll have to generalize as we collect entries.
#
# If you have a harddrive which does crazy unloading but not listed
# here, please write to linux-ide@vger.kernel.org with the outputs of
# "dmidecode" and "hdparm -I DRIVE", on a laptop the DRIVE is usually
# /dev/sda.
#
# Reported drive model: Hitachi HTS722020K9SA00
rule tp-t60
dmi system-manufacturer LENOVO
dmi system-product-name 1952W5R
dmi system-version ThinkPad T60
hal storage.model Hitachi HTS7220*K9*A*
act hdparm -B 255 $DEV
# Reported drive model: SAMSUNG HM250JI
rule hp-dv6500
dmi system-manufacturer Hewlett-Packard
dmi system-product-name HP Pavilion dv6500 Notebook PC
dmi system-version Rev 1
hal storage.model SAMSUNG HM*I
act hdparm -B 255 $DEV
# Reported drive model: ST9100824AS
rule dell-e1505
dmi system-manufacturer Dell Inc.
dmi system-product-name MM061
hal storage.model ST9*AS
act hdparm -B 255 $DEV
next prev parent reply other threads:[~2008-05-23 11:37 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-23 1:36 regarding crazy head unloads Tejun Heo
2008-05-23 11:36 ` Tejun Heo [this message]
2008-06-02 9:55 ` Scott James Remnant
2008-06-09 1:56 ` Tejun Heo
2008-09-13 11:44 ` Bruce Allen
2008-09-30 5:36 ` Tejun Heo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4836AC56.2010501@gmail.com \
--to=htejun@gmail.com \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=ballen@gravity.phys.uwm.edu \
--cc=jeff@garzik.org \
--cc=liml@rtr.ca \
--cc=linux-ide@vger.kernel.org \
--cc=roland.kletzing@materna.de \
--cc=scott@ubuntu.com \
--cc=smartmontools-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.