Difference between revisions of "Talk:How to hotswap Ultrabay devices"

From ThinkWiki
Jump to: navigation, search
(little rework ultrabay.sh)
(revork ultrabay.sh - not umounted partitions, support for holders)
Line 64: Line 64:
 
= bash script for hotswapping UltraBay =
 
= bash script for hotswapping UltraBay =
  
Here is my script for hotswapping ultrabay, is more complex, supports swap partition on drive in ultrabay and more :)
+
Here is my script for hotswapping ultrabay, is more complex, supports swap partition on drive in ultrabay, check holders (useful, when you are using luks) and more :)
  
 
{{HELP|Please test on difrent models}}
 
{{HELP|Please test on difrent models}}
Line 81: Line 81:
 
     MESSAGE="${0/*\//}: $*"
 
     MESSAGE="${0/*\//}: $*"
 
     if [ "$QUIET" = "0" ]; then
 
     if [ "$QUIET" = "0" ]; then
echo "$MESSAGE"
+
        echo "$MESSAGE"
 
     fi
 
     fi
 
     if [ "$SYSLOG" != "0" ]; then
 
     if [ "$SYSLOG" != "0" ]; then
/usr/bin/logger "$MESSAGE"
+
        /usr/bin/logger "$MESSAGE"
 
     fi
 
     fi
 
     true
 
     true
Line 92: Line 92:
 
{
 
{
 
     case "$1" in
 
     case "$1" in
"fail")
+
        "fail")
    [ $BEEP != "0" ] && echo 2 > /proc/acpi/ibm/beep
+
            [ $BEEP != "0" ] && echo 2 > /proc/acpi/ibm/beep
    exit 1
+
            exit 1
;;
+
        ;;
"success")
+
        "success")
    [ $BEEP != "0" ] && echo 12 > /proc/acpi/ibm/beep
+
            [ $BEEP != "0" ] && echo 12 > /proc/acpi/ibm/beep
    exit 0
+
            exit 0
;;
+
        ;;
 
     esac
 
     esac
 
}
 
}
Line 117: Line 117:
 
Block2Device()
 
Block2Device()
 
{
 
{
     /bin/readlink -e "/dev/block/$1"
+
     /bin/readlink -e "/dev/block/$1"  
 
}
 
}
  
Line 127: Line 127:
 
IsMounted()
 
IsMounted()
 
{
 
{
     mount | grep -q -e "^$DEVICE\b"
+
     mount | grep -q -e "^$1\b"
 
}
 
}
  
ReleaseDevice()
+
HasHolders()
 
{
 
{
     if IsMounted "$1"; then
+
     [ "$(ls "$1/holders")" ]
if ! umount "$1" &> /dev/null; then
+
}
    Message "cannot umount $DEVICE"
+
 
    false
+
IsBusy()
fi
+
{
    elif IsSwap "$1"; then
+
    DEVICE=$(Block2Device $(cat "$1/dev"))
if ! /sbin/swapoff "$1" &> /dev/null; then
+
    if IsSwap "$DEVICE" || IsMounted "$DEVICE" || HasHolders "$1"; then
    Message "cannot disable swapping on $DEVICE"
+
Message "device '$DEVICE' is busy"
    false
+
false
fi
+
    else
 +
true
 
     fi
 
     fi
 
}
 
}
Line 147: Line 148:
 
SleepDrive()
 
SleepDrive()
 
{
 
{
     if ! /sbin/hdparm -Y "$1" &> /dev/null; then
+
    BLOCK=$(cat $SCSI_DEVICE/block/*/dev 2> /dev/null)
 +
    DEVICE=$(Block2Device "$BLOCK")
 +
     if ! /sbin/hdparm -Y "$DEVICE" &> /dev/null; then
 
         Message "cannot put drive to sleep"
 
         Message "cannot put drive to sleep"
 
         if [ $FORCE_SLEEP = "0" ]; then
 
         if [ $FORCE_SLEEP = "0" ]; then
Line 160: Line 163:
 
{
 
{
 
     if ! { echo 1 > $SCSI_DEVICE/delete; } &> /dev/null; then
 
     if ! { echo 1 > $SCSI_DEVICE/delete; } &> /dev/null; then
Message "cannot delete device"
+
        Message "cannot delete device"
false
+
        false
 
     fi
 
     fi
 
}
 
}
Line 179: Line 182:
 
     { echo 0 > $(GetDock "$1")/undock; } &> /dev/null
 
     { echo 0 > $(GetDock "$1")/undock; } &> /dev/null
 
     if IsDocked "$1"; then
 
     if IsDocked "$1"; then
Message "cannot undock UltraBay"
+
        Message "cannot undock UltraBay"
false
+
        false
 
     else
 
     else
Message "UltraBay undocked"
+
        Message "UltraBay undocked"
true
+
        true
 
     fi
 
     fi
  
Line 190: Line 193:
 
while getopts "d:qlsb" OPTION; do
 
while getopts "d:qlsb" OPTION; do
 
     case $OPTION in
 
     case $OPTION in
d)
+
        d)
    SCSI_DEVICE="$OPTARG"
+
            SCSI_DEVICE="$OPTARG"
;;
+
        ;;
s)
+
        s)
    FORCE_SLEEP="0"
+
            FORCE_SLEEP="0"
;;
+
        ;;
q)
+
        q)
    QUIET="1"
+
            QUIET="1"
;;
+
        ;;
l)
+
        l)
    SYSLOG="1"
+
            SYSLOG="1"
;;
+
        ;;
b)
+
        b)
    BEEP="1"
+
            BEEP="1"
;;
+
        ;;
 
         ?)
 
         ?)
    Usage
+
            Usage
 
         ;;
 
         ;;
 
       esac
 
       esac
Line 213: Line 216:
 
if [ -d "$SCSI_DEVICE" ] && IsDocked "ata_bay"; then
 
if [ -d "$SCSI_DEVICE" ] && IsDocked "ata_bay"; then
 
     sync
 
     sync
     for BLOCK in $(/bin/cat $SCSI_DEVICE/block/*/*/dev $SCSI_DEVICE/block/*/dev 2> /dev/null); do
+
     for DEV_DIR in $(ls $SCSI_DEVICE/block/*/*/dev $SCSI_DEVICE/block/*/dev | sed -e s/dev$//  2> /dev/null); do
DEVICE=$(Block2Device "$BLOCK") && ReleaseDevice "$DEVICE" || FAIL="1"
+
IsBusy "$DEV_DIR" || Exit "fail"
 
     done
 
     done
    [ $FAIL ] && Exit "fail"
 
 
 
     sync
 
     sync
     BLOCK=$(cat $SCSI_DEVICE/block/*/dev 2> /dev/null) &&
+
     SleepDrive || Exit "fail"
    DEVICE=$(Block2Device "$BLOCK") && SleepDrive "$DEVICE" || Exit "fail"
+
     DeleteScsiDevice || Exit "fail"
    sleep 0.5
 
     DeleteScsiDevice "$SCSI_DEVICE" || Exit "fail"
 
 
     sleep 4
 
     sleep 4
 
fi
 
fi
Line 228: Line 227:
 
if [ ! -d $SCSI_DEVICE ] && $(IsDocked "ata_bay"); then
 
if [ ! -d $SCSI_DEVICE ] && $(IsDocked "ata_bay"); then
 
     if Undock "ata_bay"; then
 
     if Undock "ata_bay"; then
Exit "success"
+
        Exit "success"
 
     else
 
     else
Exit "fail"
+
        Exit "fail"
 
     fi
 
     fi
 
fi
 
fi

Revision as of 17:06, 11 June 2009

HAL script

If the script works, your lshal output should contain something similar to this. In this case the Ultrabay device was a second HDD (/dev/sdb).

Note that in the example, storage.hotpluggable = true while before it was false, so the script worked.

udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'
  block.device = '/dev/sdb'  (string)
  block.is_volume = false  (bool)
  block.major = 8  (0x8)  (int)
  block.minor = 16  (0x10)  (int)
  block.storage_device = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
  info.capabilities = {'storage', 'block'} (string list)
  info.category = 'storage'  (string)
  info.parent = '/org/freedesktop/Hal/devices/pci_8086_24ca_scsi_host_0_scsi_device_lun0'  (string)
  info.product = 'HTS726060M9AT00'  (string)
  info.udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
  info.vendor = 'ATA'  (string)
  linux.hotplug_type = 3  (0x3)  (int)
  linux.sysfs_path = '/sys/devices/pci0000:00/0000:00:1f.1/host1/target1:0:0/1:0:0:0/block/sdb'  (string)
  storage.automount_enabled_hint = true  (bool)
  storage.bus = 'pci'  (string)
  storage.drive_type = 'disk'  (string)
  storage.firmware_version = 'MH4O'  (string)
  storage.hotpluggable = true  (bool)
  storage.lun = 0  (0x0)  (int)
  storage.media_check_enabled = false  (bool)
  storage.model = 'HTS726060M9AT00'  (string)
  storage.no_partitions_hint = false  (bool)
  storage.originating_device = '/org/freedesktop/Hal/devices/computer'  (string)
  storage.partitioning_scheme = 'mbr'  (string)
  storage.removable = false  (bool)
  storage.removable.media_available = true  (bool)
  storage.removable.media_size = 60011642880  (0xdf8f90000)  (uint64)
  storage.requires_eject = false  (bool)
  storage.serial = 'SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
  storage.size = 60011642880  (0xdf8f90000)  (uint64)
  storage.vendor = 'ATA'  (string)
Known South Bridge PCI IDs
ID ThinkPad model South Bridge chip (for Ultrabay) parent device (host_0, lun0 = 2nd ATA controller, master device)
8086_7111 T20, T21, T22, X20, X21 Intel 82371AB/EB/MB PIIX4 IDE /org/freedesktop/Hal/devices/pci_8086_7111_scsi_host_0_scsi_device_lun0
8086_248a T23, T30, X22, X23, X24, X30 Intel 82801CAM IDE U100 (rev 2) /org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_0_scsi_device_lun0
8086_24ca R50, R51, T40, T40p, T41, T41p, T42, T42p, X31, X32, X40 Intel 82801DBM (ICH4-M) /org/freedesktop/Hal/devices/pci_8086_24ca_scsi_host_0_scsi_device_lun0
8086_2653 R52, T43, T43p, X41, Z60m, Z60t Intel 82801FBM (ICH6-M) /org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0
8086_27c4 R60, X60 Intel 82801GBM (ICH7 Family) /org/freedesktop/Hal/devices/pci_8086_27c4_scsi_host_scsi_device_lun0
8086_27df T60, T60p, Z61m, Z61t, Z61p Intel 82801GBM/GHM (ICH7 Family) /org/freedesktop/Hal/devices/pci_8086_27df_scsi_host_scsi_device_lun0
8086_2850 R61, T61, T61p, X300 Intel 82801H (ICH8 Family) /org/freedesktop/Hal/devices/pci_8086_2850_scsi_host_scsi_device_lun0
8086_2929 R400, R500, T400, T500, W500, W700, X200, X301 Intel 82801I ICH9 Family /org/freedesktop/Hal/devices/pci_8086_2929_scsi_host_0_scsi_device_lun0

lshal output

Please place your lshal output here if you had problems, or if you have a A or W series ThinkPad

bash script for hotswapping UltraBay

Here is my script for hotswapping ultrabay, is more complex, supports swap partition on drive in ultrabay, check holders (useful, when you are using luks) and more :)

Help needed
Please test on difrent models

ultrabay.sh

#!/bin/bash
SCSI_DEVICE=""
FORCE_SLEEP="1"
QUIET="0"
SYSLOG="0"
BEEP="0"

Message()
{
    MESSAGE="${0/*\//}: $*"
    if [ "$QUIET" = "0" ]; then
        echo "$MESSAGE"
    fi
    if [ "$SYSLOG" != "0" ]; then
        /usr/bin/logger "$MESSAGE"
    fi
    true
}

Exit()
{
    case "$1" in
        "fail")
            [ $BEEP != "0" ] && echo 2 > /proc/acpi/ibm/beep
            exit 1
        ;;
        "success")
            [ $BEEP != "0" ] && echo 12 > /proc/acpi/ibm/beep
            exit 0
        ;;
    esac
}

Usage()
{
    echo "usage: ${0/*\/} [options]"
    echo "options:"
    echo "    -d <path>  SCSI device (required)"
    echo "    -s         Ignore fail when putting drive to sleep"
    echo "    -q         No messages"
    echo "    -l         Use syslog for messages (-q has no efect)"
    echo "    -b         Use beeb for notification (-q has no efect)"
    exit 1
}

Block2Device()
{
    /bin/readlink -e "/dev/block/$1"    
}

IsSwap()
{
    /sbin/swapon -s | grep -q -e "^$1\b"
}

IsMounted()
{
    mount | grep -q -e "^$1\b"
}

HasHolders()
{
    [ "$(ls "$1/holders")" ]
}

IsBusy()
{
    DEVICE=$(Block2Device $(cat "$1/dev")) 
    if IsSwap "$DEVICE" || IsMounted "$DEVICE" || HasHolders "$1"; then
	Message "device '$DEVICE' is busy"
	false
    else
	true
    fi
}

SleepDrive()
{
    BLOCK=$(cat $SCSI_DEVICE/block/*/dev 2> /dev/null)
    DEVICE=$(Block2Device "$BLOCK")
    if ! /sbin/hdparm -Y "$DEVICE" &> /dev/null; then
        Message "cannot put drive to sleep"
        if [ $FORCE_SLEEP = "0" ]; then
            true
        else
            false
        fi
    fi
}

DeleteScsiDevice()
{
    if ! { echo 1 > $SCSI_DEVICE/delete; } &> /dev/null; then
        Message "cannot delete device"
        false
    fi
}

GetDock()
{
    grep "$1" /sys/devices/platform/dock.*/type | sed -e s%/type:.*%%
}

IsDocked()
{
    [ $(cat $(GetDock "$1")/docked) -ne 0 ]
}

Undock()
{
    { echo 0 > $(GetDock "$1")/undock; } &> /dev/null
    if IsDocked "$1"; then
        Message "cannot undock UltraBay"
        false
    else
        Message "UltraBay undocked"
        true
    fi

}

while getopts "d:qlsb" OPTION; do
    case $OPTION in
        d)
            SCSI_DEVICE="$OPTARG"
        ;;
        s)
            FORCE_SLEEP="0"
        ;;
        q)
            QUIET="1"
        ;;
        l)
            SYSLOG="1"
        ;;
        b)
            BEEP="1"
        ;;
        ?)
            Usage
        ;;
      esac
done
 
if [ -d "$SCSI_DEVICE" ] && IsDocked "ata_bay"; then
    sync
    for DEV_DIR in $(ls $SCSI_DEVICE/block/*/*/dev $SCSI_DEVICE/block/*/dev | sed -e s/dev$//  2> /dev/null); do
	IsBusy "$DEV_DIR" || Exit "fail"
    done
    sync
    SleepDrive || Exit "fail"
    DeleteScsiDevice || Exit "fail"
    sleep 4
fi

if [ ! -d $SCSI_DEVICE ] && $(IsDocked "ata_bay"); then
    if Undock "ata_bay"; then
        Exit "success"
    else
        Exit "fail"
    fi
fi

Message "UltraBay is already undock"
Exit "success"

Supported models: R400 - linux-2.6.29

comments

Interesting, especially the support for swap partitions. but I have two comments, first your calling your script hotswap.sh and then having udev call ultrabay.sh?

Then your hard coding the location of the Ultrabay device. This is not guarenteed to be correct, although it will be in most cases. In particular the A and W-series machines. A-series had support for more then one Ultrabay device, while W-series has support for more then one internal HDD in addition to the Ultrabay device, so the Ultrabay location will shift. That is why the Ultrabay Eject script on the main page gets the eject device information from udev.

comments

Hi, thanks, I fix name of script :) Udev calling ultrabay.sh with option -d, so it remove correct device, if you want remove device manualy, is default device useful. But option may be required...

more comments ;)

You might also have a look at the script on the main page, it has a few extra abilities, such as logging to syslog, beeping and putting up popups on the desktop.

Logging to syslog is simple, just call 'logger' with what you want to log. quite should have no effect on this.

For beeps, similar to what windows does you can echo different values to /proc/acpi/ibm/beep, but it only works if sound is not muted. Unfortunately doing so does seem to generate some annoying messages in syslog.

Lastly you can use notify-send to put up messages on the desktop, but before you can do so you have to do an export DISPLADISPLAY=0:0 /usr/bin/knotify4 --passive-popup : Adresář nebo soubor neexistujeY=:0.0

Syslog and beep

OK, scrip now support syslog and beeping :).


Still missing notify-send ;)

I am also thinking that it would be useful in the case of a busy filesystem to tell the user to run something like fuser -mv /dev/sr0
Or perhaps we should run it ourselves automatically and just tell the user what is the cause of the busy filesystem.
--Tonko 21:21, 8 June 2009 (UTC)