Western Digital MyBook World Edition spindown

Short intro

While searching for information how to automatically spindown SATA devices without using ACPI, I have found the following post on some forum:

http://martin.hinner.info/mybook/spindown.php from Martin Hinner.

Information

This method is originally explained in http://gentoo-wiki.com/HOWTO_HDD_spindown_small_server and http://kyyhkynen.net/stuff/mybook/.
I have just modified the needed scripts to work on MBWE.

Contents

Making WD MyBook World Edition cool and quiet

  1. Make sure you are in superuser mode

    # su
    
  2. Update hdparm. The default busybox version of hdparm is broken, it reports the state of the disks always as "active/idle", even if the disk is in standby mode.

    Make a directory for source files

    # mkdir /tmp/src/
    # cd /tmp/src/
    

    Download and install hdparm

    # wget http://download.sourceforge.net/sourceforge/hdparm/hdparm-7.7.tar.gz
    # tar -zxvf hdparm-7.7.tar.gz
    # cd hdparm-7.7
    # ./configure
    # make
    # make install
    # cd ..
    # rm -rf hdparm-7.7*
    

    Do not play with hdparm unless you really know what you are doing, you might end up with a damaged hard drive.

  3. Get the smart_spindown script, place it to /usr/sbin and its access rights

    # wget http://kyyhkynen.net/stuff/mybook/smart_spindown
    # mv smart_spindown /usr/sbin
    # chmod 0700 /usr/sbin/smart_spindown
    # chown root:root /usr/sbin/smart_spindown
    
  4. Then you should tinker with the settings in the beginning of the smart_spindown (see comments in the script for details). At this time just set the name(s) of your disk(s).

    You might want to first test drive the script with the logging output echoed to stdout. So don't touch the lines involving logging just yet.

    Also, leave the WAITTIME (= the amount of time in seconds of disk inactivity to wait before spinning the disks down) to a fairly small amount so you don't have to wait too long. 60 or 120 will do just fine, just set it to a longer period after you have tested that the script works. I have mine set to 300 (= 5 minutes).

    #!/bin/bash
    #
    # smart_spindown
    #
    # Copyright (C) 2003 by Bart Samwel
    #
    # You may do with this file (and parts thereof) whatever you want, as long
    # as my copyright notice is retained.
    #
    # Extended by joerk at gentoo-wiki.com
    # Modified to fit WD MyBook World external hard drives by kyyhkynen at gmail.com
    #
    ###################################################################
    #
    # Configuration
    #
    # Disk(s) to monitor.
    # If you have only one disk, leave DISK2=sdb empty
    DISK1=sda
    DISK2=
    
    # The base "no reads" wait time (in seconds). This is multiplied by
    # the backoff factor to determine the real "no reads" wait time.
    WAITTIME=300
    
    # The maximum "no reads" wait time (in seconds).
    # This also limits the backoff factor: the backoff factor cannot increase
    # above a value that makes the "no reads" wait time larger than MAXWAIT.
    # Default is 1200 seconds.
    MAXWAIT=1200
    
    # Time (in seconds) between polls to see if the disk is active again.
    # Default is 30 seconds.
    POLLTIME=30
    
    # Output levels. Level 2 is verbose, level 1 is normal output.
    # Enable all levels you would like to see.
    OUTLEVEL1=true
    OUTLEVEL2=true
    
    # Decide which output to use. Useful if run in daemon mode
    # echo or logger
    # output1 is logged to normal, output2 to debug syslog
    # Is PID of this shell logged?
    OUTPUT1=echo
    OUTPUT2=echo
    #OUTPUTTAG="$(basename -- $0)[$$]"
    #OUTPUT1="logger -t $OUTPUTTAG -p user.notice --"
    #OUTPUT2="logger -t $OUTPUTTAG -p user.debug  --"
    
    #
    # End of configuration. You shouldn't have to change lines below this :)
    #
    #########################################################################
    
    # Device name(s) for the disk(s).
    DEVNAME1=/dev/$DISK1
    [ "$DISK2" ] && DEVNAME2=/dev/$DISK2
    [ -z "$DISK2" ] && DEVNAME2=
    
    # Stats file: the file used to monitor the disk's read activity.
    # The first entry in this stats file must represent the read activity.
    STATSFILE1=/sys/block/$DISK1/stat
    STATSFILE2=/sys/block/$DISK2/stat
    
    # Multiplication factor for the backoff after a spinup, in percentages.
    # Default is 300 = factor 3.
    BACKOFF_INCREASE_PCT=400
    
    # Multiplication factor for the backoff at every poll that shows that
    # the disk is spun down. This determines how fast the backoff value
    # decreases.
    BACKOFF_DECREASE_PCT=98
    
    # Enable this if you don't use laptop_mode. This will make the script
    # sync before spinning down the disc. To make this work, you must
    # ensure that:
    # 1. /proc/sys/vm/dirty_expire_centisecs is set to a high value. You can
    #    use 60000 for 10 minutes.
    # 2. /proc/sys/vm/dirty_writeback_centisecs is set to the same value.
    # 3. Your ext3 filesystems are mounted with "commit=n", where n is the
    #    number of seconds between commit. Use 600 for 10 minutes.
    NO_LAPTOP_MODE=true
    
    
    
    #
    # Let's go!
    #
    
    # Number of poll times that the disc was found to be spun down.
    POLLSSPUNDOWN=0
    
    # Number of spindowns performed
    SPINDOWNS=0
    
    # Number of times (*100) the WAITTIME of no-reads required before spindown
    BACKOFF_FACTOR=100
    
    # Stats: Total time the disk has been up.
    UPTIME=0
    
    # Total duration of last spun-down period.
    LASTDOWNTIME=-1
    
    # Total duration of the last spun-up period.
    LASTUPTIME=0
    
    # Duration of the last poll. Always equal to POLLTIME except the first
    # time around.
    LASTPOLLTIME=0
    
    # Make sure the stuff we use is in the cache. I've seen it happen
    # that the script spun the disk down, and then "sleep" wasn't in
    # the cache and the disk spun right up again. :)
    true
    false
    sleep 1
    
    # Log the end of script execution
    trap "$OUTPUT1 'Exiting.'" EXIT
    
    
    if [ "$DISK2" ] ; then
    	$OUTLEVEL1 && ${OUTPUT1} "Monitoring spindown opportunities for disks $DISK1 and $DISK2." ;
    else
    	$OUTLEVEL1 && ${OUTPUT1} "Monituring spindown opportunities for disk $DISK1." ;
    fi ;
    if ($OUTLEVEL1) ; then
    	hdparm -C $DEVNAME1 $DEVNAME2 |grep active >/dev/null
    	if [ "$?" == "0" ] ; then
    		[ "$DISK2" ] && ${OUTPUT1} "A drive is currently spun up." ;
    		[ -z "$DISK2" ] && ${OUTPUT1} "The drive is currently spun up." ;
    	else
    		[ "$DISK2" ] && ${OUTPUT1} "Both drives are currently spun down." ;
    		[ -z "$DISK2" ] && ${OUTPUT1} "The drive is currently spun down." ;
    	fi ;
    fi
    while [[ /sbin/true ]]; do
    	hdparm -C $DEVNAME1 $DEVNAME2 |grep active >/dev/null
    	if [ "$?" == "0" ] ; then
    		THISWAIT=$(($WAITTIME*$BACKOFF_FACTOR/100)) ;
    		if [[ $THISWAIT -gt $MAXWAIT ]] ; then
    			THISWAIT=$MAXWAIT ;
    		fi ;
    		# Increase the backoff irrespective of whether we failed
    		# or not. The backoff should drop again by the lack of
    		# spinups afterwards.
    		BACKOFF_FACTOR=$(($BACKOFF_FACTOR*$BACKOFF_INCREASE_PCT/100)) ;
    		if [[ $(($BACKOFF_FACTOR*$WAITTIME/100)) -gt $MAXWAIT ]] ; then
    			BACKOFF_FACTOR=$(($MAXWAIT*100/$WAITTIME)) ;
    		fi ;
    		UPTIME=$(($UPTIME+$LASTPOLLTIME)) ;
    		LASTUPTIME=$(($LASTUPTIME+$LASTPOLLTIME)) ;
    		if [ "$LASTDOWNTIME" -ge "0" ] ; then
    			$OUTLEVEL1 && ${OUTPUT1} "A drive spun up after $LASTDOWNTIME seconds. Total time up/down: $UPTIME/$(($POLLSSPUNDOWN*$POLLTIME)) (avg sleep time $(($POLLSSPUNDOWN*$POLLTIME/$SPINDOWNS)))" ;
    		fi
    		PREVIOUS_READS_DISK1=-1 ;
    		PREVIOUS_READS_DISK2=-1 ;
    		NEXT_READS_DISK1=-1 ;
    		NEXT_READS_DISK2=-1 ;
    		NUM_EQUALS=0 ;
    		$OUTLEVEL2 && ${OUTPUT2} "Waiting for $THISWAIT seconds of read inactivity..." ;
    		PREVIOUS_READS_DISK1=`cat $STATSFILE1 |awk '{ print $1; }'` ;
    		[ "$DISK2" ] && PREVIOUS_READS_DISK2=`cat $STATSFILE2 |awk '{ print $1; }'` ;
    		while [[ $(($NUM_EQUALS*5)) -lt $THISWAIT ]]; do
    			sleep 5 ;
    			UPTIME=$(($UPTIME+5)) ;
    			LASTUPTIME=$(($LASTUPTIME+5)) ;
    			NEXT_READS_DISK1=`cat $STATSFILE1 |awk '{ print $1; }'` ;
    			[ "$DISK2" ] && NEXT_READS_DISK2=`cat $STATSFILE2 |awk '{ print $1; }'` ;
    			if [[ $PREVIOUS_READS_DISK1 -ne $NEXT_READS_DISK1 ]] ; then
    				NUM_EQUALS=0 ;
    				PREVIOUS_READS_DISK1=$NEXT_READS_DISK1 ;
    				$OUTLEVEL2 && ${OUTPUT2} "$DISK1 read, restarting..." ;
    			else
    				if [ "$DISK2" -a $PREVIOUS_READS_DISK2 -ne $NEXT_READS_DISK2 ] ; then
    					NUM_EQUALS=0 ;
    					PREVIOUS_READS_DISK2=$NEXT_READS_DISK2 ;
    					$OUTLEVEL2 && ${OUTPUT2} "$DISK2 read, restarting..." ;
    				else
    					NUM_EQUALS=$(($NUM_EQUALS+1)) ;
    					$OUTLEVEL2 && ${OUTPUT2} "Seconds of quiet: $(($NUM_EQUALS*5))" ;
    				fi
    			fi
    		done
    		# We've just had $THISWAIT seconds of read inactivity. Writes can be
    		# cached, reads always spin up the disk; the inactivity indicates
    		# that we're ready to go to sleep. Laptop mode will have synced all
    		# writes for us after the last read, so we don't have to explicitly
    		# sync.
    		if ( $NO_LAPTOP_MODE ) ; then
    			sync ;
    		fi ;
    		hdparm -q -y $DEVNAME1 $DEVNAME2 ;
    		SPINDOWNS=$(($SPINDOWNS+1)) ;
    		$OUTLEVEL1 && ${OUTPUT1} "Drive(s) spun down after $LASTUPTIME seconds (with $THISWAIT seconds of inactivity), total spin down count: ${SPINDOWNS}." ;
    		LASTUPTIME=0 ;
    		LASTDOWNTIME=0 ;
    	else
    		POLLSSPUNDOWN=$(($POLLSSPUNDOWN+1)) ;
    		if [[ $SPINDOWNS -eq 0 ]] ; then
    			SPINDOWNS=1 ;
    		fi
    		LASTDOWNTIME=$(($LASTDOWNTIME+$LASTPOLLTIME)) ;
    		BACKOFF_FACTOR=$(($BACKOFF_FACTOR*$BACKOFF_DECREASE_PCT/100)) ;
    		if [ $BACKOFF_FACTOR -lt 100 ] ; then
    			BACKOFF_FACTOR=100 ;
    		fi
    	fi ;
    	if ( $OUTLEVEL2 ) ; then
    		${OUTPUT2} "spindowns: $SPINDOWNS, time up/down: $UPTIME/$(($POLLSSPUNDOWN*$POLLTIME)), backoff $BACKOFF_FACTOR, down for $LASTDOWNTIME (avg $(($POLLSSPUNDOWN*$POLLTIME/$SPINDOWNS)))." ;
    	fi ;
    	sleep $POLLTIME ;
    	LASTPOLLTIME=$POLLTIME ;
    done
    
  5. Now let's test the script. First, set the kernel parameters so that the disk writes will be cached. Later on, the service startup script will take care of these, but now that we are only testing, we'll have to set them manually.

    # echo 0 > /proc/sys/vm/dirty_expire_centisecs
    # echo 0 > /proc/sys/vm/dirty_writeback_centisecs
    # echo 95 > /proc/sys/vm/dirty_ratio
    # echo 10 > /proc/sys/vm/dirty_background_ratio
    # echo 5 > /proc/sys/vm/laptop_mode
    # echo 40 > /proc/sys/vm/swappiness
    

    If you are interested in how each of the paremeters affect the system, here is a brief explanation.

    Start the script, don't do anything else with the MBWE and watch the output. If you have the box nearby, you'll probably also hear the spin-downs and spin-ups.

    # /usr/sbin/smart_spindown
    

    Leave the script running for a couple of hours and you'll see if the disks spin up unintentionally. If they do, you'll probably have to reduce the disk usage somehow.

    With my MBWE it seems to take some time after a reboot for the script to start really working. So wait patiently. Leave the script running for example for a night. Even if it keeps spinning up and down, one night doensn't probably kill your disks, right? :)

  6. If the script works just fine, kill it by pressing CTRL+C.

    Now tweak the settings in the beginning of the script. Set the WAITTIME to serve your needs; I have mine set to 300 (= 5 minutes). Then set the MAXWAIT (= the amount of time in seconds of disk inactivity to wait at most, the time is changing dynamically between WAITTIME and MAXWAIT) accordingly.

    Also, mind the logging options. If you would like to log the output to syslog, uncomment the lines with logger. To disable logging and thus reduce disk activity, set both OUTLEVEL1 and OUTLEVEL2 to false.

  7. Next, we'll make the script start and stop automatically.

    Download the script to start/stop the service, put it into /etc/init.d/ and set its access rights. Then make a symbolic link to stop the service when the MBWE is shutting down.

    # wget http://kyyhkynen.net/stuff/mybook/S50smart_spindown
    # mv S50smart_spindown /etc/init.d	
    # chmod 0700 /etc/init.d/S50smart_spindown
    # chown root:root /etc/init.d/S50smart_spindown
    # ln -s /etc/init.d/S50smart_spindown /etc/init.d/K50smart_spindown
    

    The scripts in the directory /etc/init.d/ starting with S[number] are automatically run during system startup with parameter start. The number defines the order the scripts are run. Likewise, scripts starting with K[number] are run when the system is shutting down with parameter stop.

  8. This step is optional. If the script seems to work ok for you, you don't necessarily need to do this. You can try this also later if you find it necessary. Edit your fstab with caution; you might mess your drives up by playing around with it.

    Find this line in /etc/fstab:

    /dev/md3    /var    ext3    defaults,noatime    0   2
    

    Change it into this:

    /dev/md3    /var    ext3    defaults,noatime,commit=43200    0   2
    

    Changing this line causes the filesystem on /var (where log files and all frequently accessed stuff is located) to commit its journal to the disk only twice a day, thus reducing disk access.

  9. Reboot your MBWE.

    # reboot
    

    You will lose your SSH connection during the boot, so reconnect to the MBWE.

    The script should be now running. You can check it like this:

    # ps -A | grep smart
    
  10. You're done here. Enjoy your new sleepy MBWE.

    If you want to tweak your settings without rebooting the whole device, just make your changes to the script and restart it by

    # /etc/init.d/S50smart_spindown restart
    

    If your disk(s) keep spinning up randomly, see next section for further tips.

Back to the top

Western Digital MyBook World Edition spindown

Reducing disk usage

Introduction

There are many running services in your MBWE that access the disks, thus making it spin up when it really shouldn't. I addition, they are using memory, which the MBWE doesn't have to spare. Here we'll turn some of them off.

The how-to

  1. Make sure you are in superuser mode

    # su
    
  2. Disable mionet. It uses lots of memory. If you really want to securely access your MBWE from anywhere, I strongly recommend using SSH/SFTP.

    In order to prevent mionet from starting during boot, edit /etc/init.d/mionet.sh.
    Comment out this line:

    $MIONETD start
    

    Then stop the service:

    # /etc/init.d/mionet.sh stop
    
  3. Disable the cron job that is writing the time to a file. I really haven't figured out where the file is even used.

    Edit /etc/crontabs/root.
    Comment out the only line that can be commented out (if you havent set any cron jobs of your own):

    7   *   *   *   *   date +%m%d ...
    
  4. Disable the service that displays the disk usage with the leds in the front panel of your MBWE. Admit it, the feature is pretty much useless and because the service has to check the amount of free space on the disk(s), it is causing disk access.

    In order to prevent the service from starting during boot, edit /etc/init.d/S15wdc-fuel-gauge. Comment out this line:

    $FGD &
    

    Then stop the service:

    # /etc/init.d/S15wdc-fuel-gauge stop
    
  5. Disable ntpd log. You really don't need to know that stuff.

    Edit /etc/ntp.conf.
    just point the logfile to /dev/null

    logfile /dev/null

    Restart ntpd to reload the configuration.

    # /etc/init.d/ntp.sh restart

    Of course, you could disable the whole ntpd and update the clock only during boot or with a cron job. But it is up to you.

  6. Disable the default temperature monitoring service. More on that in the next section.

  7. Disable syslogd and klogd. If you don't know what they are used for, you won't need them. And, you can always start them if you need to debug something.

    Of course, you could move the logs to your ramdisk (see next step), but the busybox version of syslogd doesn't support a syslog.conf configuration file that could be used to move the logfiles to another location. So you would need to update syslogd to do that.

    To prevent them from starting, edit /etc/inittab. Comment out these lines:

    ::respawn:/sbin/syslogd -n -m 0
    ::respawn:/sbin/klogd -n

    Reboot.

  8. Create a RAM disk and keep all the frequently accessed log files, ntp.drift and samba's .tdb files there. If you dont't know how a RAM disk works or what is is, I recommend reading the wikipedia article before proceeding.

    Again, if you don't know your Linux, you might screw up your MBWE big time. so proceed with caution.

    You're probably wondering, "weren't we supposed to free some memory instead of using it more?" Well that is up to you... my RAM disk eats one megabyte of memory, and it's half empty, so one could probably do with an even smaller ram disk.

    The basic idea is to create a small RAM disk, configure the programs to use it and copy the data on it back to the disk when the disk is spinning.

    In this example, we'll be moving just ntp.drift and samba's files to the RAM disk. ntp.drift, because it is written frequently (if you have ntpd running) and samba, because it spins my MBWE up every time I start my Windows machine up and it mounts the samba share.

    Of course, you could have disabled ntpd and might not have problem with samba spinning the disks up, but you may set up other programs to use the RAM disk, too. From this guide you'll get the basic idea how to do it, though.

     

    First, we'll create a RAM disk manually. Later on, you can do this with a startup script automatically, but let's just do it manually for practise :)

    By default, the busybox linux used in the MBWE has five RAM disk devices, that are by default inactive and not in use. You can list them with

    # ls -l /dev/ram*

    Let's format a filesystem to ram1:

    # /sbin/mke2fs -vm 0 /dev/ram1 1024

    The number 1024 defines the size of the RAM disk in kilobytes. One megabyte should be more than enough.

    Next, we'll have to mount the disk. We will mount the ramdisk to /mnt/ramdisk/. You may use another path, but then you'll have to remember to configure the programs accordingly.

    # mkdir /mnt/ramdisk
    # /bin/mount -t ext2 /dev/ram1 /mnt/ramdisk/

    And behold, we have a working RAM disk.

    Then, let's configure ntpd to keep the drift file on the RAM disk by editing /etc/ntp.conf. The drift file contains the estimated clock frequency error and it is updated whenever the ntpd checks the time from the time server. Find the line beginning with driftfile and change it to

    driftfile /mnt/ramdisk/ntp.drift

    Then copy the driftfile to the RAM disk and restart ntpd:

    # cp /etc/ntp.drift /mnt/ramdisk
    # /etc/init.d/ntp.sh restart

    Next, configure samba to use the ramdisk. Edit /var/oxsemi/smb.conf and change the following lines:

    smb passwd file=/mnt/ramdisk/private/smbpasswd
    private dir=/mnt/ramdisk/private
    log file=/mnt/ramdisk/log.%m
    lock directory=/mnt/ramdisk/locks
    pid directory=/mnt/ramdisk/locks
    

    Edit /etc/init.d/samba.sh and set the log directory to the RAM disk by editing the line in the start function:

    /usr/local/samba/sbin/nmbd -D -s/var/oxsemi/smb.conf -l/mnt/ramdisk

    Finally edit /etc/inetd.conf and change the log directory there, too :

    netbios-ssn stream tcp nowait root /usr/local/samba/sbin/smbd smbd -s/var/oxsemi/smb.conf -l/mnt/ramdisk -d0

    Next, copy the files to the RAM disk:

    # mkdir /mnt/ramdisk/locks
    # cp /var/locks/* /mnt/ramdisk/locks/
    # mkdir /mnt/ramdisk/private
    # cp /var/private/* /mnt/ramdisk/private/
    # cp /var/log/log.* /mnt/ramdisk/

    Then, restart samba:

    # /etc/init.d/samba.sh restart

    If everything went well, and you got no errors, samba and ntpd are now using the RAM disk.

    Now, this process should be made to happen automatically during boot. You can either roll your own startup script or just use mine:

    # wget http://kyyhkynen.net/stuff/mybook/S13ramdisk
    # mv S13ramdisk /etc/init.d	
    # chmod 0700 /etc/init.d/S13ramdisk
    # chown root:root /etc/init.d/S13ramdisk
    # ln -s /etc/init.d/S13ramdisk /etc/init.d/K71ramdisk

    The script looks like this:

    #!/bin/sh
    #
    
    case "$1" in
        start)
    	/sbin/mke2fs -vm 0 /dev/ram1 1024
    	/bin/mount -t ext2 /dev/ram1 /mnt/ramdisk/
    	
    	cp /etc/ntp.drift /mnt/ramdisk/
    	cp /var/log/log.* /mnt/ramdisk/
    	mkdir /mnt/ramdisk/locks
    	cp /var/locks/* /mnt/ramdisk/locks/
    	mkdir /mnt/ramdisk/private
    	cp /var/private/* /mnt/ramdisk/private/
    	
    	;;
    
        backup)
        	cp /mnt/ramdisk/ntp.drift /etc/
        	cp /mnt/ramdisk/locks/* /var/locks/
    	cp /mnt/ramdisk/log.* /var/log/
    	cp /mnt/ramdisk/private/* /var/private/	
    	;;
    
        stop)
    	$0 backup
    	;;
    
        restart|reload)
    	$0 backup
    	;;
    
        *)
    	echo $"Usage: $0 {start|stop|restart|backup}"
    	exit 1
    esac
    
    exit $?
    

    As you an see, with parameter start, the RAM disk is created and the needed files are copied to it. With parameter backup the files are copied back to the disk.

    Note: the order the RAM disk script is run during the startup is important; the RAM disk must be created before any services using it are started.

    Because all the data on the RAM disk is lost in case of a power failure, you probably should copy the files on the RAM disk back to the disk more often than just during a shut down. I have done this by adding a line to the smart_spindown script to the point where the disk spin up is detected. This way, the RAM disk is copied back to the disk every time the disk has spun up, thus keeping the files pretty much up to date.

    In order to do this, find the following line in the smart_spindown script:

    THISWAIT=$(($WAITTIME*$BACKOFF_FACTOR/100)) ;

    It should be line number 142, if you haven't added any lines to the beignning of the script. Before that line, add a line containing:

    /etc/init.d/S13ramdisk backup

    And restart the smart_spindown script:

    # /etc/init.d/S50smart_spindown restart

    And behold, your RAM disk is backed up to the disk every time the disk(s) start spinning.

  9. Copy the whole system to an USB stick and run it from there. Frequently written files could be kept on a ram disk (see previous step) to maximize the USB stick's lifetime.

    I haven't really tried this, it's just an idea. This would really minimize disk access, if it was possible. And why wouldn't it be, this is linux we're talking about here :)

    Any ideas concerning this would be appereciated...

    The needed steps would be:

    1. Clone system files to an USB stick. My current system files take about 350 megabytes of space, so a 512 MB stick should be enough.

    2. During boot, check if there is an USB drive plugged in and if it contains the system files. Could also perform some checks to ensure the stick is healthy.

    3. chroot to the stick and continue running the system from there.

Back to the top

Western Digital MyBook World Edition spindown

How to find out what is causing the disk to spin up and down

Introduction

Ok, so your MBWE keeps spinning up and down and you want to find out what's causing it? Here's how to do it.

The how-to

  1. Make sure you are in superuser mode

    # su
  2. First, you have to stop syslogd and klogd if you haven't already done that. We will be logging disk access and we don't want it to be logged on a log file, thus causing disk activity, which causes more log entries, which causes more disk access... and so on. You got the point. If you didn't, don't mess with your MBWE.

    To prevent them from starting, edit /etc/inittab. Comment out these lines:

    ::respawn:/sbin/syslogd -n -m 0
    ::respawn:/sbin/klogd -n
  3. Reboot.

  4. Enable I/O debugging

    # echo 1 > /proc/sys/vm/block_dump
  5. Now, all that's happening in your disks will be logged to your kernel ring buffer. You'll see its contents with

    # dmesg

    The output will have lots of stuff from your last boot in the beginning, so you might want to clear the buffer with

    # dmesg -c
  6. Now, leave your MBWE alone for a while.

    After a while, your ring buffer will be full of lines like

    <7>dmesg(10078): READ block 2525104 on md1

    Typically, one line describes one block access. First, there is the name of the executable, then its process id and finally the description of what happened. So this line means that dmesg was reading the disk (md1).

    When a process is writing to the disk, the line will look like:

    <7>tail(10976): dirtied inode 45 (temperature.log) on ram1

    This means that tail was writing to the file temperature.log on my ram disk. Actually, the data has been written to the write buffer in memory and will be written to the disk after a while. The actual write will be indicated by a line like this:

    <7>pdflush(36): WRITE block 984 on ram1
  7. So, after your MBWE spins up unintentionally, check with dmesg what was causing it.

    Remember to turn off I/O debugging off afterwards with

    # echo 0 > /proc/sys/vm/block_dump
Back to the top

Western Digital MyBook World Edition spindown

Alternative Temperature Monitoring and Fan Control

Introduction

With the default temperature monitoring service on the MBWE, you can't set the limits for when the fan should be spinning how fast. With my simple replacement shell script you can.

Note: if you own the MBWE I i.e. the single disk version, this script is pretty much useless, since the single disk version doesn't have a fan.

Prerequisites

Enabled SSH access.

A text editor and the know-how to use it. I recommend installing nano, but vi will also do just fine.

An up-to-date version of hdparm. See the first section for installation instructions.

The how-to

  1. Make sure you are in superuser mode

    # su
  2. Disable the original temperature monitoring service. Edit the file /etc/init.d/S15wdc-heat-monitor. Comment out this line:

    $HEAT_MON &

    Then stop the service

    # /etc/init.d/S15wdc-heat-monitor stop

    Download my shell script and the script used to start it as a service, move them to right places and set treir access rights:

    # wget http://kyyhkynen.net/stuff/mybook/temperature_monitor
    # mv temperature_monitor /usr/sbin
    # chmod 0700 /usr/sbin/temperature_monitor
    # chown root:root /usr/sbin/temperature_monitor
    # wget http://kyyhkynen.net/stuff/mybook/S51temperature_monitor
    # mv S51temperature_monitor /etc/init.d
    # chmod 0700 /etc/init.d/S51temperature_monitor
    # chown root:root /etc/init.d/S51temperature_monitor
    # ln -s /etc/init.d/S51temperature_monitor /etc/init.d/K51temperature_monitor

    The scripts in the directory /etc/init.d/ starting with S[number] are automatically run during system startup with parameter start. The number defines the order the scripts are run. Likewise, scripts starting with K[number] are run when the system is shutting down with parameter stop.

  3. Edit the settings in the beginning of the script (see comments in the script for details).

    #!/bin/sh
    # An alternative temperature monitoring and fan control script for 
    # WD MyBook World Edition external hard drives
    #
    # Copyright (C) 2007 by kyyhkynen at gmail.com
    #
    # You may do with this file (and parts thereof) whatever you want, as long
    # as my copyright notice is retained.
    #
    #######################################################################
    #
    # Configuration settings
    #
    # Disk(s) to monitor.
    # If you have only one disk, leave DISK2 empty
    # In that case, however, this script is pretty much useless.
    DISK1=sda
    DISK2=sdb
    
    # Temperature limits for speeds.
    # When the temperature of the disk(s) drop below TEMP_LIMIT_0, the fan speed is set to 0
    # When the temperature of the disk(s) is between the limits, the fan speed is set to 50
    # When the temperature of the disk(s) is above TEMP_LIMIT_50, the fan speed is set to 100
    TEMP_LIMIT_0=43
    TEMP_LIMIT_50=55
    
    # The amount of time (in minutes) to wait before turning the fan off after the disk(s) have been spun down.
    SPINDOWN_WAIT=10
    
    # Logging stuff
    LOG_ENABLED=false
    LOG_INTERVAL=5
    LOGGER=echo
    
    #
    # End of configuration. You shouldn't need to touch lines below this :)
    #
    #######################################################################
    
    # Device name(s) for the disk(s).
    DEVNAME1=/dev/${DISK1}
    DEVNAME2=/dev/${DISK2}
    
    # The file controlling the fan speed
    FAN_SPEED=/sys/devices/platform/wdc-fan/speed
    
    # Get current fan speed
    CURRENT_FAN_SPEED=`cat ${FAN_SPEED}` ;
    
    LOG_COUNTER=0
    SPINDOWN_COUNTER=0
    
    while [[ /bin/true ]]; do
    	
    	TEMPERATURE_DISK1=$(smartctl -d ata -A ${DEVNAME1}|grep Tempera|cut -c 88-90) ;
    	
    	hdparm -C $DEVNAME1 |grep active >/dev/null
    	if [ "$?" == "0" ] ; then
    		STATUS_DISK1=u ;
    	else
    		STATUS_DISK1=d ;
    	fi ;
    
    	if [ -z "$DISK2" ] ; then
    		TEMPERATURE_DISK2=$TEMPERATURE_DISK1 ;
    		STATUS_DISK2=$STATUS_DISK1 ;
    	else
    		TEMPERATURE_DISK2=$(smartctl -d ata -A ${DEVNAME2}|grep Tempera|cut -c 88-90) ;
    		hdparm -C $DEVNAME2 |grep active >/dev/null
    		if [ "$?" == "0" ] ; then
    			STATUS_DISK2=u ;
    		else
    			STATUS_DISK2=d ;
    		fi ;
    	fi ;
    
    	if [ $STATUS_DISK1 = "d" -a $STATUS_DISK2 = "d" ] ; then
    		if [ $CURRENT_FAN_SPEED -gt 0 ] ; then
    			SPINDOWN_COUNTER=$((SPINDOWN_COUNTER+1)) ;
    			if [[ $SPINDOWN_COUNTER -ge $SPINDOWN_WAIT ]] ; then
    				echo 0 > $FAN_SPEED ;
    				CURRENT_FAN_SPEED=0 ;
    				SPINDOWN_COUNTER=0 ;
    			fi ;
    		fi ;
    	else
    		if [ $TEMPERATURE_DISK1 -ge $TEMP_LIMIT_0 -o $TEMPERATURE_DISK2 -ge $TEMP_LIMIT_0 ] ; then
    			if [ $TEMPERATURE_DISK1 -ge $TEMP_LIMIT_50 -o $TEMPERATURE_DISK2 -ge $TEMP_LIMIT_50 ] ; then
    				echo 100 > $FAN_SPEED ;
    				CURRENT_FAN_SPEED=100 ;
    			else
    				if [ $CURRENT_FAN_SPEED -lt 50 ] ; then
    					echo 100 > $FAN_SPEED ;
    					sleep 2 ;
    				fi ;
    				echo 50 > $FAN_SPEED ;
    				CURRENT_FAN_SPEED=50 ;
    			fi ;
    		else
    			echo 0 > $FAN_SPEED ;
    			CURRENT_FAN_SPEED=0 ;
    		fi ;
    	fi ;
    
    	LOG_COUNTER=$((LOG_COUNTER+1));
    	if [[ $LOG_COUNTER -ge $LOG_INTERVAL ]] ; then
    		$LOG_ENABLED && ${LOGGER} "${TEMPERATURE_DISK1}${STATUS_DISK1} ${TEMPERATURE_DISK2}${STATUS_DISK2} ${CURRENT_FAN_SPEED}" ;
    		LOG_COUNTER=0 ;
    	fi ;
    	sleep 60 ;
    done
    
  4. Start the service.

    # /etc/init.d/S51temperature_monitor start
  5. You're done.

    If you want to tweak your settings, just edit the script and restart the service afterwards with

    # /etc/init.d/S51temperature_monitor restart
  6. Hint: if you turn on the logging, you can build nice graphs of your drive temperature with the data (see example).

Back to the top


Hit Counter by Digits