Package: hdparm
Version: 6.1-2
Severity: normal
Tags: patch

The current behaviour of hdparm is that it will refuse to set options
for any disks if one RAID array is in the process of resynchronisation.
This is somewhat too conservative: As far as I know, the real problem with
setting harddisk options while the RAID array is being resynchronised
is that hdparm and the RAID system is competing with each other for
the disk I/O, nothing else (nothing to do with the resynchronisation
process itself).

It is possible to suspend the resynchronisation before setting
the harddisk options, and resuming the resynchronisation afterwards
(thus there will be no I/O on the disk while hdparm is performing its
task). The benefit of this approach is that the sysadmin does not have
to manually check harddisk options after an unclean boot, still hdparm
can be run safely.

Regarding the detection of resynchronisation, there's at least one more
state of the RAID system which the current hdparm init script does
not recognise as synchronisation, but it should. If one disk fails,
and there's a spare disk assigned to the same array, the RAID system
immediately takes this disk into use, and starts to synchronise the
contents to this disk; but this state shows in the /proc/mdstat file as
'recover', not 'resync'. Just to be complete, I looked into the 2.6.16
kernel sources, and found two more states that can show up in
/proc/mdstat: 'repair' and 'check'. To be honest, I don't know these
two, but I think that hdparm should consider these the same as 'resync'
and 'recover', to err on the safe side.

Attached a patch that contains the above fixes. (Sorry, the patch is for
the Sarge version of hdparm, and then for the installed scripts and not
for the package source.)

Bye,

norbi

-- System Information:
Debian Release: 3.1
Architecture: i386 (i686)
Kernel: Linux 2.6.16
Locale: LANG=C, LC_CTYPE=hu_HU (charmap=ISO-8859-2)

Versions of packages hdparm depends on:
ii  libc6                 2.3.2.ds1-22sarge3 GNU C Library: Shared libraries an

-- no debconf information
--- /etc/init.d/hdparm  2005-04-18 20:40:03.000000000 +0200
+++ /etc/init.d/hdparm.fixed    2006-05-07 15:40:40.000000000 +0200
@@ -8,6 +8,12 @@
 #
 #See /usr/share/doc/hdparm/README.Debian for more details.
 
+# Defaults for configuration variables.
+RAID_WORKAROUND=yes
+
+# Source the defaults file.
+[ -e /etc/default/hdparm ] && . /etc/default/hdparm
+
 case "$0" in
   *hdparm)
     FIRST=yes
@@ -32,9 +38,38 @@
 report_error_and_exit()
 {
   report_error "$*.  Exiting."
+
+  # Turn on RAID synchronisation if we turned it off.
+  if [ "$raidstat" != 'OK' ] && [ "$RAID_WORKAROUND" = "yes" ]; then
+    undo_slow_down_raid_sync
+  fi
+
   exit 1
 }
 
+slow_down_raid_sync()
+{
+  if [ -f /proc/sys/dev/raid/speed_limit_min ]; then
+    raid_speed_limit_min=`cat /proc/sys/dev/raid/speed_limit_min`
+    echo 0 >/proc/sys/dev/raid/speed_limit_min
+  fi
+  if [ -f /proc/sys/dev/raid/speed_limit_max ]; then
+    raid_speed_limit_max=`cat /proc/sys/dev/raid/speed_limit_max`
+    echo 0 >/proc/sys/dev/raid/speed_limit_max
+  fi
+  sleep 2
+}
+
+undo_slow_down_raid_sync()
+{
+  if [ -f /proc/sys/dev/raid/speed_limit_min ] && [ "x$raid_speed_limit_min" 
!= "x" ]; then
+    echo $raid_speed_limit_min >/proc/sys/dev/raid/speed_limit_min
+  fi
+  if [ -f /proc/sys/dev/raid/speed_limit_max ] && [ "x$raid_speed_limit_max" 
!= "x" ]; then
+    echo $raid_speed_limit_max >/proc/sys/dev/raid/speed_limit_max
+  fi
+}
+
 case $1 in
   start|restart|reload|force-reload)
     ;;
@@ -55,14 +90,14 @@
   
   raidstat=OK
   if [ -e /proc/mdstat ]; then
-    if grep -iq resync /proc/mdstat; then
+    if egrep -iq "resync|repair|recover|check" /proc/mdstat; then
       raidstat=RESYNC
     fi
   elif [ -e /proc/rd/status ]; then
     raidstat=`cat /proc/rd/status`
   fi
   
-  if ! [ "$raidstat" = 'OK' ]; then
+  if [ "$raidstat" != 'OK' ] && [ "$RAID_WORKAROUND" != "yes" ]; then
     report_error "*** RAID status not OK.  Exiting. ***"
     exit 0
   fi
@@ -126,12 +161,15 @@
 
 ITEMS_ECHOED=no
 
+# Turn off RAID synchronisation if needed and asked for.
+if [ "$raidstat" != 'OK' ] && [ "$RAID_WORKAROUND" = "yes" ]; then
+  slow_down_raid_sync
+fi
+
 # Get blocks as far as the drive's write cache.
 /bin/sync
 
 # Set options for a group of disks in /etc/default/hdparm
-[ -e /etc/default/hdparm ] && . /etc/default/hdparm
-
 if [ -n "$harddisks" -a -n "$hdparm_opts" ]; then
   for drive in $harddisks; do 
     /sbin/hdparm -q -f $drive
@@ -302,3 +340,8 @@
     echo " (none)."
   fi
 }
+
+# Turn back on RAID synchronisation if we turned it off.
+if [ "$raidstat" != 'OK' ] && [ "$RAID_WORKAROUND" = "yes" ]; then
+  undo_slow_down_raid_sync
+fi
--- /etc/default/hdparm 2005-05-24 16:08:23.000000000 +0200
+++ /etc/default/hdparm.fixed   2006-05-07 15:35:13.000000000 +0200
@@ -9,3 +9,11 @@
 #
 # harddisks=""
 # hdparm_opts=""
+
+# By default, hdparm will refuse to set harddisk options on any drive
+# if the system has software RAID running, and one or more disk arrays
+# are in the process of resynchronisation.
+# With this variable set to 'yes', /etc/init.d/hdparm will suspend the
+# RAID resynchronisation process before setting harddisk options, and
+# will resume it after setting is done.
+RAID_WORKAROUND=yes

Reply via email to