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

From ThinkWiki
Jump to: navigation, search
(Ultrabay Hotswap on ThinkPad X41)
(hdparm -Y removed from script for Ultrabay eject: new section)
 
(41 intermediate revisions by 10 users not shown)
Line 1: Line 1:
I recently tried using the libata-tj patch tarball for 2.6.16.16, applying this against the newly released 2.6.16.18 kernel (released today.)  Patch applied cleanly.  Upon boot, I immediately get a multitude of "weird" errors -- strange lockups, programs segmentation fault (running "top" resulted in a seg fault), and ultimately a hard lockup.
+
=Recent Ubuntu versions=
 +
I think, it must be mentioned that hotswapping Ultrabay devices using recent distros
 +
is by far not that hard as before. I'm using Ubuntu 9.04 on Z61m and in my case hotswapping
 +
Ultrabay DVD-RW works out-of-the-box without any scripts or whatsoever. The article
 +
however suggests that one always needs some ejecting scripts which might confuse certain
 +
users. So it would be nice to add something like: "If you are using Ubuntu *.** everything should
 +
work out-of-the-box"
  
I booted back to my vanilla 2.6.16.16, ran fsck (appeared to just replay a few transactions, no major damage), and am back to normal.  However, it successfully scared me off - unfortunately can't risk too much downtime (or worse, subtle fs corruption) right now on my main system.  Anybody have experiences with this on a T43p using piix driver?
+
--[[User:Bombenbach|Bombenbach]] 12:01, 9 August 2009 (UTC)
  
--[[User:gsmenden|gsmenden]] 00:00, 23 May 2006 (EST)
+
Really? Did you try to swap out a Ultrabay device with mounted filesystem? Good luck!
----
+
The udev handler and eject script are there for a reason. By default no action is taken when you pull out a device, which can cause real problems if not handled properly.
  
The 2.6.16.16 patch works fine on my T43. There's a git tree (mentioned on the patch's webpage) which is closer to 2.6.18, but AFAIK no simple unified patch was prepred.
+
--[[User:Tonko|Tonko]] 09:31, 10 August 2009 (UTC)
  
--[[User:Thinker|Thinker]] 08:37, 23 May 2006 (CEST)
+
Well, actually I couldn't imagine that someone would like to pull out an Ultrabay device with mounted file system.
----
+
As far a usb flash drives are concerned, you won't do that either, right? My point was, that if the file system is '''properly unmounted''', I can simply pull my Ultrabay DVD-RW out without any freezes or crashes. And when I put it back again, the drive is automatically recognized by Ubuntu so that I can use it. I don't have an Ultrabay HDD, but I assume that if it works with DVD-RW it also should work with HDD. Correct me if I'm wrong. If the sole purpose of eject script is hotswapping Ultrabay devices '''with mounted filesystem''' then I still think that it would be nice to point it out in the article.
  
Cool.  If I get brave I'll try it again on the 43p against 2.6.16.16 proper and report back.
+
--[[User:Bombenbach|Bombenbach]] 07:52, 11 August 2009 (UTC)
  
--[[User:gsmenden|gsmenden]] 15:29, 23 May 2006 (EST)
+
By default on most modern distributions based on a recent kernel with libata, the libata driver gets to cleanup the mess after the fact, if you pull out an ultrabay device without first
----
+
* unmounting the filesystem
 +
* powering down the device
 +
You may be lucky, or you might end up with a hung system, corrupted filesystem, etc. Your choice.
  
Works fine here on 2.6.16.
+
There is work going on upstream to resolve this with DeviceKit-disks, but that depends on a patch to the Linux kernel, which has not made it in yet, since right now there is no correlation between the udev event and the actual Bay device, and since you can have multiple Bay devices (in fact your ThinkPad likely has 3) this correlation is needed, otherwise DeviceKit-disks would need to know about every single Laptop out there and the mapping between the Bay numbering and the actual devices (something the kernel can easily just provide instead).
I got only one crash with Suspend to Ram, which I'm unable to reproduce yet.
 
I renamed the acpi event files because at least my acpid doesn't read files that ends with .conf
 
  
--[[User:Defiant|Defiant]] 21:09, 28 May 2006 (CEST)
+
Here is a Feature request against DeviceKit-disks that provides some status information
 +
http://bugs.freedesktop.org/show_bug.cgi?id=23110
  
----
+
--[[User:Tonko|Tonko]] 09:07, 11 August 2009 (UTC)
Update - patched against 2.6.16.19, works fine.  It appears my previous problems were due to a disk error unrelated to the patch.  Excellent!
 
  
--[[User:gsmenden|gsmenden]] 00:57, 31 May 2006 (EST)
+
=HAL script=
  
Anybody have time to make a patch of the libata(-tj) .git tree against the recently released 2.6.17?  I hope to make one in the future if not...
+
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).
  
--[[User:gsmenden|gsmenden]] 22:08, 19 Jun 2006 (EST)
+
Note that in the example, storage.hotpluggable = true while before it was false, so the script worked.
 
+
<pre>
== one nit about ultrabay_close script / patch against 2.6.17 available ==
+
udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'
 
+
  block.device = '/dev/sdb'  (string)
Howdy,
+
  block.is_volume = false  (bool)
 
+
  block.major = 8  (0x8)  (int)
In ultrabay_close, there is 'sleep 3' for disk spinup, which isn't necessarylibata itself waits for disk spinup and if something breaks (e.g. first reset fails w/ timeout or something), it's libata's fault. Please remove that line and see if anything breaks.
+
  block.minor = 16  (0x10)  (int)
 
+
  block.storage_device = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
Also, I've uploaded patch against 2.6.17/2.6.17.1 today.
+
  info.capabilities = {'storage', 'block'} (string list)
 
+
  info.category = 'storage' (string)
http://home-tj.org/files/libata-tj-stable/libata-tj-2.6.17-20060625-1.tar.bz2
+
  info.parent = '/org/freedesktop/Hal/devices/pci_8086_24ca_scsi_host_0_scsi_device_lun0'  (string)
 
+
  info.product = 'HTS726060M9AT00(string)
Hmmm... My post looks different from others.  This wasn't intentional.  Just don't know how to add normal discussion entry. Sorry.
+
  info.udi = '/org/freedesktop/Hal/devices/storage_serial_SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
 
+
  info.vendor = 'ATA(string)
--tj
+
  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)
Right, it works fine without "sleep 3" using the new patches. Sleep removed.
+
  storage.bus = 'pci'  (string)
 
+
  storage.drive_type = 'disk'  (string)
--[[User:Thinker|Thinker]] 12:35, 1 July 2006 (CEST)
+
  storage.firmware_version = 'MH4O'  (string)
----
+
  storage.hotpluggable = true  (bool)
 
+
  storage.lun = 0  (0x0)  (int)
Is it correct, that the ata_piix driver in kernel 2.6.18 RC4 now supports hot swapping like described in the howto and announced here http://lwn.net/Articles/183734/?
+
  storage.media_check_enabled = false  (bool)
 
+
  storage.model = 'HTS726060M9AT00'  (string)
--[[User:cob|cob]] 15:53, 23 August 2006
+
  storage.no_partitions_hint = false (bool)
 
+
  storage.originating_device = '/org/freedesktop/Hal/devices/computer'  (string)
== T42 freezing up when trying to hot swap ultrabay. ==
+
  storage.partitioning_scheme = 'mbr'  (string)
 
+
  storage.removable = false  (bool)
Hi,
+
  storage.removable.media_available = true  (bool)
 
+
  storage.removable.media_size = 60011642880  (0xdf8f90000)  (uint64)
Please bear with meI am totally new at this and I am making my best effort to understand and learn.  
+
  storage.requires_eject = false  (bool)
 
+
  storage.serial = 'SATA_HTS726060M9AT00_MRH453M4H11ARB'  (string)
My problem is that when typing "# echo eject > /proc/acpi/ibm/bay" to eject my ultrabay and put another in, I see the power going off in the ultrabay LED, but then my PC freezes completely.  
+
  storage.size = 60011642880  (0xdf8f90000) (uint64)
 
+
  storage.vendor = 'ATA'  (string)
I am running Fedora 6 Test 3, kernel 2.6.17-1.2647 and my notebook is a ThinkPad T42.
+
</pre>
 
 
Please help! I have to constantly be changing my bay to use information in other hard drives, and I have to shutdown the system completely to not have any problems.  
 
  
Thanks,
+
{| border=1
 +
|+ 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 || A20m, A20p, A21e, A21m, A21p, A22e, A22m, A22p, 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_248a || A30, A30p, A31, A31p|| Intel 82801CAM IDE U100 (rev 2) || /org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_scsi_device_lun0_0<br>/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
  
--Barny  09/21/2006@7:46PM EST
+
lshal of my A31: [http://nopaste.org/p/a4p6x9tSob http://nopaste.org/p/a4p6x9tSob]
  
----
+
Thanks! If I understand the output correctly you have one Toshiba Combo DVD-ROM/CD-RW R2002 in one ultrabay connected as slave to the primary IDE controller, and one Toshiba DVD-ROM C2512 in the second ultrabay connected as master to the secondary IDE controller. Can you confirm? I have added it to the table.
Have the same problem on a T40p running SuSE 10.1. Also lt_hotplug module is of no help. Keep me informed in case you have a solution!
 
Thanks,
 
--[[User:Ays|Ays]] 19:49, 5 October 2006 (CEST)
 
  
----
 
  
I have no problems with kernel 2.6.17-1.2187_1.fc5.cu from suspend2 on my T42p running Fedora Core 5. I have compiled the lt_hotswap module and every thing works fine. Since kernel 2.6.18-1.2200.fc5 my system freeez on loading the modul or on calling "echo eject > /proc/acpi/ibm/bay".
+
I have a Thinkpad T43 and I found out from my lshal output that I had to use parent device:
Any ideas what has changed in the kernel?
+
pci_8086_2653_scsi_host_0_scsi_device_lun0 instead of
 +
pci_8086_2653_scsi_host_scsi_device_lun0 (notice the added 0).
 +
This is the ultrabay, however, the internal disk still use the "original" parent device (the one without the 0).
 +
I think this information should be added to the table.
 +
Specs:
 +
Thinkpad T43 (machine type 2668),
 +
Mandriva One 2009.1,
 +
haldaemon 0.5.12
  
--CoolMischa 2006-11-06@13:24 CET
+
Thanks, it is possible that you have AHCI mode disabled in the BIOS for your HDD?
 +
--[[User:Tonko|Tonko]] 11:00, 31 July 2009 (UTC)
  
== Second disk not seen correctly on reinsert (T43p) [solved] ==
+
===Thinkpad T510===
 
+
The T510 uses the Arrandale chipset, or "Intel Corporation 5 Series/3400 Series Chipset". This seems to work for me:
(update: see below for solution)
 
 
 
I have followed the instructions on my T43p running Gentoo using 2.6.18. I have a second hard disk in the UltraBay, using ata_piix, so it is seen as /dev/sdb (as described in [[Problems with SATA and Linux#No_DMA_on_system_hard_disk|Problems with SATA and Linux]]). The eject works fine. When I reinsert it and issue the rescan command, Only the main /dev/sdb device reappears, but not the ones corresponding to the partitions (/dev/sdb1, etc.), so I cannot mount them, and fdisk /dev/sdb says that it cannot open the device.
 
 
 
In dmesg, I see a bunch of errors like these, repeated multiple times:
 
  
 
<pre>
 
<pre>
sd 1:0:0:0: SCSI error: return code = 0x08000002
+
        <!-- Lenovo ThinkPad T510 -->
sdb: Current: sense key=0xb
+
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T510">
    ASC=0x0 ASCQ=0x0
+
          <match key="storage.bus" string_outof="pci;scsi">
end_request: I/O error, dev sdb, sector 0
+
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_3b2f_scsi_host_0_scsi_device_lun0">
ata2: EH complete
+
              <merge key="storage.hotpluggable" type="bool">true</merge>
ata2.00: speed down requested but no transfer mode left
+
            </match>
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
+
          </match>
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
+
        </match>
ata2: EH complete
 
ata2.00: speed down requested but no transfer mode left
 
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
 
ata2: EH complete
 
ata2.00: speed down requested but no transfer mode left
 
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
 
ata2: EH complete
 
ata2.00: speed down requested but no transfer mode left
 
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
 
ata2: EH complete
 
ata2.00: speed down requested but no transfer mode left
 
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
 
ata2: EH complete
 
ata2.00: speed down requested but no transfer mode left
 
ata2.00: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x0
 
ata2.00: tag 0 cmd 0x20 Emask 0x1 stat 0x51 err 0x4 (device error)
 
 
</pre>
 
</pre>
 +
--[[User:Jicama|Jicama]] 01:58, 7 November 2010 (UTC)
  
And at the end:
+
= bash script for hotswapping UltraBay =
  
<pre>
+
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 :)
sdb: Current: sense key=0xb
 
    ASC=0x0 ASCQ=0x0
 
end_request: I/O error, dev sdb, sector 0
 
ata2: EH complete
 
SCSI device sdb: 117210240 512-byte hdwr sectors (60012 MB)
 
sdb: Write Protect is off
 
sdb: Mode Sense: 00 3a 00 00
 
SCSI device sdb: drive cache: write back
 
SCSI device sdb: 117210240 512-byte hdwr sectors (60012 MB)
 
sdb: Write Protect is off
 
sdb: Mode Sense: 00 3a 00 00
 
SCSI device sdb: drive cache: write back
 
</pre>
 
  
The situation is not cured by a reboot (I still see only /dev/sdb), I have to power cycle to get the devices back.
+
{{HELP|Please test on difrent models}}
  
Thanks for any ideas.
+
ultrabay.sh
 +
<pre>
 +
#!/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
 +
}
  
(2006-10-10) As a followup to my note above, I have noticed that the DVD-RW drive works perfectly after hot-swapping it - it's just the second hard disk that doesg not get recognized properly. I can "scsiping" the /dev/sdb device and it seems to respond OK, I have tried restarting udevd without success, and I'm at a loss as to what to try next.
+
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 effect)"
 +
    echo "    -b        Use beep for notification (-q has no effect)"
 +
    exit 1
 +
}
  
It turned out to be an obvious problem - I had a disk password set on my second disk, so on reinsert it could not be accessed. I turned off the disk password, and now it works perfectly.
+
Block2Device()
 +
{
 +
    /bin/readlink -e "/dev/block/$1"   
 +
}
  
== ultrabay_open: Problem when using /proc/mounts ==
+
IsSwap()
 +
{
 +
    /sbin/swapon -s | grep -q -e "^$1\b"
 +
}
  
I am just working on a perl-free version of the ultrabay_open script. When the script reads the currently mounted devices from /proc/mounts, it may not find all the relevant device files. A file system mounted with a relative device path given to the mount command doesn't show up with the absolute device path in /proc/mounts. Example:
+
IsMounted()
 +
{
 +
    mount | grep -q -e "^$1\b"
 +
}
  
{{cmdroot|cd /dev/; mount sdb5 /mnt}} results in the following line in {{path|/proc/mounts}}:
+
HasHolders()
 +
{
 +
    [ "$(ls "$1/holders")" ]
 +
}
  
{{cmdresult|sdb5 /mnt ext3 rw 0 0}}
+
IsBusy()
 +
{
 +
    DEVICE=$(Block2Device $(cat "$1/dev"))
 +
    if IsSwap "$DEVICE" || IsMounted "$DEVICE" || HasHolders "$1"; then
 +
Message "device '$DEVICE' is busy"
 +
false
 +
    else
 +
true
 +
    fi
 +
}
  
{{path|/etc/mtab}} contains the needed information:
+
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
 +
}
  
{{cmdresult|/dev/sdb5 /mnt ext3 rw 0 0}}
+
DeleteScsiDevice()
 +
{
 +
    if ! { echo 1 > $SCSI_DEVICE/delete; } &> /dev/null; then
 +
        Message "cannot delete device"
 +
        false
 +
    fi
 +
}
  
However, /proc/mounts is the more reliable source of information IMHO. The absolute device path is needed to find out its major and minor numbers.
+
GetDock()
 +
{
 +
    grep "$1" /sys/devices/platform/dock.*/type | sed -e s%/type:.*%%
 +
}
  
Any suggestions?
+
IsDocked()
 +
{
 +
    [ $(cat $(GetDock "$1")/docked) -ne 0 ]
 +
}
  
--[[User:Acolomb|MinioN]] 01:03, 28 December 2006 (CET)
+
Undock()
 +
{
 +
    { echo 0 > $(GetDock "$1")/undock; } &> /dev/null
 +
    if IsDocked "$1"; then
 +
        Message "cannot undock UltraBay"
 +
        false
 +
    else
 +
        Message "UltraBay undocked"
 +
        true
 +
    fi
  
== Can/t  mount CD after reinsert on X41 ==
+
}
  
I did all the steps described on this page, and the drive ejects fine, and then when I
+
while getopts "d:qlsb" OPTION; do
reinsert it the /dev/scd0 entry reappears, but when I insert a CD Gnome won't mount it
+
    case $OPTION in
automatically, and when I try manually I ger this message:
+
        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
  
     mount: wrong fs type, bad option, bad superblock on /dev/scd0,
+
if [ ! -d $SCSI_DEVICE ] && $(IsDocked "ata_bay"); then
     missing codepage or other error
+
    if Undock "ata_bay"; then
 +
        Exit "success"
 +
     else
 +
        Exit "fail"
 +
     fi
 +
fi
  
and dmesg says:
+
Message "UltraBay is already undocked"
 +
Exit "success"
 +
</pre>
  
    isofs_fill_super: bread failed, dev=sr0, iso_blknum=16, block=16
+
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?
  
I have to reboot to use the drive again.
+
Then your hard coding the location of the Ultrabay device. This is not guaranteed 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.
  
P.S. I discovered the following in dmesg when I boot:
+
==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...
  
    ata2.01: qc timeout (cmd 0xa1)
+
==more comments ;)==
    ata2.01: failed to IDENTIFY (I/O error, err_mask=0x4)
+
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.
    ata2: failed to recover some devices, retrying in 5 secs
 
    ata2.01: qc timeout (cmd 0xa1)
 
    ata2.01: failed to IDENTIFY (I/O error, err_mask=0x4)
 
    ata2: failed to recover some devices, retrying in 5 secs
 
    ata2.01: qc timeout (cmd 0xa1)
 
    ata2.01: failed to IDENTIFY (I/O error, err_mask=0x4)
 
    ata2: failed to recover some devices, retrying in 5 secs
 
    ata2.00: configured for UDMA/33
 
  
Is that relevant?
+
Logging to syslog is simple, just call 'logger' with what you want to log. quite should have no effect on this.
  
== hdparm -Y /dev/<devnode> ==
+
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.
  
is the hdparm part in the ultrabay_eject script really necessary?
+
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
  
It does not work with my dvdram drive (R60):
+
==Syslog and beep==
 +
OK, scrip now support syslog and beeping :).
  
hdparm -Y /dev/sdb
 
 
/dev/sdb:
 
issuing sleep command
 
HDIO_DRIVE_CMD(sleep) failed: Input/output error
 
  
thanks,
 
  
== problem with umount_rdev ==
+
Still missing notify-send ;)
  
I tried out the ultrabay_eject script and get this error (debian lenny with kernel 2.6.22.3)
+
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<br>
 +
Or perhaps we should run it ourselves automatically and just tell the user what is the cause of the busy filesystem.<br>
 +
--[[User:Tonko|Tonko]] 21:21, 8 June 2009 (UTC)
  
cat: /sys/class/scsi_device/1:0:0:0/device/block:*/*/dev: No such file or directory
+
== get notify-send working ==
  
What is wrong? Why I need the output of $ULTRABAY_SYSDIR/block\:*/*/dev in
+
Hi there,
  
unmount_rdev `cat $ULTRABAY_SYSDIR/block\:*/dev    /
+
I've modified your ultrabay_eject script so that the notify-send is working for the user which is logged onto screen :0
$ULTRABAY_SYSDIR/block\:*/*/dev`  \
+
for an unified diff see below, here is the whole modified script
  
?
+
* whole script
== hotswap with kernel 2.6.24 and archlinux ==
+
<pre>
Since I change to kernle 2.6.24 on my archlinux hotswap isn't working anymore. When I try to swap between harddisk and DVD-drive the system frezzes and the only way to get it back to work ist turn the power of.
+
#!/bin/bash
Has anyone else the same problem? And is there a way to fix it?
 
  
---
+
# Change the following DEVPATH= to match your system, if you want to run this directly instead of having it called by the udev eject script
 +
# To find the right value, insert the UltraBay optical drive and run:
 +
# udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!'
 +
if [ "$DEVPATH" = "" ]
 +
then
 +
  DEVPATH="/devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0"
 +
fi
  
Yes I stumbled today(6.Apr.) over this annoying regression: On my T42p 2373-KYG with Kubuntu 8.04 Hardy Heron
+
shopt -s nullglob
Kubuntu is freezing totally after only removing the DVD drive from the UltraBay slot.
+
export DISPLAY=:0.0 # required for notify-send
This happens on a T42p upgraded from Gutsy and on another T42p with a clean and fresh Hardy install. (/Lophiomys)
 
  
---
+
DISP0_USER=`lastlog | grep "[[:space:]]:0" | awk '{ print $1 }'` # the [[:space:]] before the :0 is needed to exclude ipv6 adresses
 +
DISP0_USER_HOME=`getent passwd ${DISP0_USER} | cut -d':' -f6`
 +
export XAUTHORITY=${DISP0_USER_HOME}/.Xauthority # also required for notify-send
  
I think I may know what is causing the issue:  Disable ACPI support on libata, or switch to thinkpad-acpi [deprecated] bay support.  The bay module is not able to load on 2.6.24+ if libata is compiled with ACPI support.
+
ULTRABAY_SYSDIR=/sys$DEVPATH
  
--[[User:Hmh|hmh]] 06:30, 7 May 2008 (CEST)
+
# Find generic dock interface for UltraBay
 
+
dock=$( /bin/grep -l ata_bay /sys/devices/platform/dock.?/type )
Could you help out with instructions for an interim workaround, how to disable ACPI support on libdata or switch to thinkpad-acpi? Thanks.
+
dock=${dock%%/type}
 
+
if [ -n "$dock" -a -d "$dock" ]; then
--[[User:Lophiomys|lophiomys]] 19:13, 7 May 2008 (CEST)
+
        logger ultrabay_eject starting eject of $dock
 
+
else
== Ultrabay Hotswap on ThinkPad X41 ==
+
        logger ultrabay_eject cannot locate bay dock device
 
+
        notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Cannot locate bay dock device"
After several hours of debugging and trial+error, I managed to get hotswaping ultrabay devices working in Fedora 9. The kernels I tested were 2.6.25.11 and 2.6.25.14 from fedora updates. The bay.ko driver was not present in the kernel so I just used the ibm-acpi driver (works fine). You need to create only 4 files (/usr/sbin/ultrabay_insert; /usr/sbin/ultrabay_eject; /etc/acpi/events/ultrabay-insert and /etc/acpi/events/ultrabay-eject) available from the linnk here: [http://www.thinkwiki.org/wiki/How_to_hotswap_UltraBay_devices]. NOTE!! - DO NOT use the ultrabay_eject script from the link as it won't work. I have a modified version that works below. I have tested swapping dvdrw with an hdd and it works just fine. Make sure you restart acpid after adding the scripts. Hope this works for others..
+
fi
 
 
/usr/sbin/ultrabay_eject:
 
 
 
<pre>
 
#!/bin/bash
 
ULTRABAY_SYSDIR='/sys/class/scsi_device/1:0:0:0/device'
 
shopt -s nullglob
 
  
 
# Umount the filesystem(s) backed by the given major:minor device(s)
 
# Umount the filesystem(s) backed by the given major:minor device(s)
 
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
 
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
for $major_minor (@ARGV) {
+
        for $major_minor (@ARGV) {
$major_minor =~ m/^(\d+):(\d+)$/ or die;
+
                $major_minor =~ m/^(\d+):(\d+)$/ or die;
push(@tgt_rdevs, ($1<<8)|$2);
+
                push(@tgt_rdevs, ($1<<8)|$2);
}
+
        }
 
         # Sort by reverse length of mount point, to unmount sub-directories first
 
         # Sort by reverse length of mount point, to unmount sub-directories first
 
         open MOUNTS,"</proc/mounts" or die "$!";
 
         open MOUNTS,"</proc/mounts" or die "$!";
Line 268: Line 384:
 
         foreach $m (@mounts) {
 
         foreach $m (@mounts) {
 
                 ($dev,$dir)=@$m;
 
                 ($dev,$dir)=@$m;
next unless -b $dev;  $rdev=(stat($dev))[6];
+
                next unless -b $dev;  $rdev=(stat($dev))[6];
next unless grep($_==$rdev, @tgt_rdevs);
+
                next unless grep($_==$rdev, @tgt_rdevs);
system("umount","-v","$dir")==0  or  $bad=1;
+
                system("umount","-v","$dir")==0  or  $bad=1;
}
+
                if ($bad == 1) {
exit 1 if $bad;
+
                        system("logger","ultrabay_eject","ERROR unmounting",$dev,$dir);
 +
                        system("notify-send -u critical -t 100000 \"Error unmounting $dir\" \"Unmounting of $dir on $dev failed!\"");
 +
                } else {
 +
                        system("logger","ultrabay_eject","unmounted",$dev,$dir);
 +
                        system("notify-send -u normal -t 5000 \"Unmounted $dir\"");
 +
                };
 +
        }
 +
        exit 1 if $bad;
 
EOPERL
 
EOPERL
 
}
 
}
Line 278: Line 401:
 
# Get the UltraBay's /dev/foo block device node
 
# Get the UltraBay's /dev/foo block device node
 
ultrabay_dev_node() {
 
ultrabay_dev_node() {
UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block/"*`" || return 1
+
        UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block/"*`" || return 1
UDEV_NAME="`udevinfo -q name -p $UDEV_PATH`" || return 1
+
        UDEV_NAME="`udevadm info --query=name --path=$UDEV_PATH`" || return 1
echo /dev/$UDEV_NAME
+
        echo /dev/$UDEV_NAME
 
}
 
}
  
if [ -d $ULTRABAY_SYSDIR ]; then
+
if [ $( cat $dock/docked ) == 0 ]; then
sync
+
        logger ultrabay_eject dock reports empty
# Unmount filesystems backed by this device
+
else
unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev    \
+
if [ -d $ULTRABAY_SYSDIR ]; then
                  $ULTRABAY_SYSDIR/block/*/*/dev`  \
+
logger ultrabay_eject dock occupied, shutting down storage device $DEVPATH
|| {
+
sync
echo 10 > /proc/acpi/ibm/beep; # error tone
+
# Unmount filesystems backed by this device
exit 1;
+
## This seems to be very inelegant and prone to failure
}
+
unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev    \
        sync
+
  $ULTRABAY_SYSDIR/block/*/*/dev`  \
        # Nicely power off the device
+
|| {
DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE
+
logger ultrabay_eject umounting failed
        # Let HAL+KDE notice the unmount and let the disk spin down
+
echo 2 > /proc/acpi/ibm/beep  # triple error tone
sleep 0.5
+
notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Please do not pull the device, doing so could cause file corruption and possibly hang the system. Unmounting of the filesystem on the ThinkPad Ultrabay device failed. Please put the eject leaver back in place, and try to unmount the filesystem manually. If this succeeds you can try the eject again"
# Unregister this SCSI device:
+
exit 1;
sync
+
}
echo 1 > $ULTRABAY_SYSDIR/delete
+
sync
 +
# Nicely power off the device
 +
DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE
 +
# Let HAL+KDE notice the unmount and let the disk spin down
 +
sleep 0.5
 +
# Unregister this SCSI device:
 +
sync
 +
echo 1 > $ULTRABAY_SYSDIR/delete
 +
else
 +
logger ultrabay_eject bay occupied but incorrect device path $DEVPATH
 +
notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Bay occupied but incorrect device path"
 +
echo 2 > /proc/acpi/ibm/beep  # triple error tone
 +
exit 1
 +
fi
 
fi
 
fi
  
# We really need a 3 sec pause here otherwise the system will freeze..
+
# We need sleep here so someone can disconnect the bay and the drive
sleep 3
+
sleep 1
 +
 
 +
# Turn off power to the UltraBay
 +
logger ultrabay_eject undocking $dock
 +
echo 1 > $dock/undock
  
# Turn off power to the UltraBay:
 
if [ -d /sys/devices/platform/bay.0 ]; then
 
echo 1 > /sys/devices/platform/bay.0/eject
 
elif [ -e /proc/acpi/ibm/bay ]; then
 
echo eject > /proc/acpi/ibm/bay
 
fi
 
 
# Tell the user we're OK
 
# Tell the user we're OK
 +
logger ultrabay_eject done
 
echo 12 > /proc/acpi/ibm/beep
 
echo 12 > /proc/acpi/ibm/beep
 +
notify-send -u normal -t 10000 "Safe to remove device" "The ThinkPad Ultrabay device can now safely be removed"
 +
 +
</pre>
 +
 +
*unified diff
 +
<pre>
 +
--- ultrabay_eject.orig 2010-01-07 22:51:40.000000000 +0100
 +
+++ ultrabay_eject 2010-01-07 22:54:55.000000000 +0100
 +
@@ -10,6 +10,11 @@
 +
 +
shopt -s nullglob
 +
export DISPLAY=:0.0 # required for notify-send
 +
+
 +
+DISP0_USER=`lastlog | grep "[[:space:]]:0" | awk '{ print $1 }'` # the [[:space:]] before the :0 is needed to exclude ipv6 adresses
 +
+DISP0_USER_HOME=`getent passwd ${DISP0_USER} | cut -d':' -f6`
 +
+export XAUTHORITY=${DISP0_USER_HOME}/.Xauthority # also required for notify-send
 +
+
 +
ULTRABAY_SYSDIR=/sys$DEVPATH
 +
 +
# Find generic dock interface for UltraBay
 
</pre>
 
</pre>
  
zin 26 August 2008
+
i hope this is useful to other users as well --[[User:Roo|Roo]] 22:19, 7 January 2010 (UTC)
 +
 
 +
= A warning about sysfs docked =
 +
 
 +
A note to script writers/users:  [https://marc.info/?l=linux-acpi&m=148952016304094&w=2 The docked sysfs attribute can be unreliable.]  Be sure the script fails safely if it reports 0 when there are docked devices.
 +
 
 +
--[[User:Kevinoid|Kevinoid]] ([[User talk:Kevinoid|talk]]) 20:45, 14 March 2017 (CET)
 +
 
 +
== hdparm -Y removed from script for Ultrabay eject ==
 +
 
 +
Previously the [[How_to_hotswap_Ultrabay_devices#Script_for_Ultrabay_eject|Script for Ultrabay eject]] invoked <code>hdparm -Y</code> before <code>echo 1 > $ULTRABAY_SYSDIR/delete</code>.  From the comment, it appears that the intent was to spin down the drive before deleting the ATA device.  Unfortunately, this is both unnecessary,  [https://lore.kernel.org/linux-scsi/b6da4b95-f6e4-4cf7-9cdc-239d91655b6d@kernel.org/ since it is done automatically by the kernel], and counterproductive, since [https://lore.kernel.org/linux-scsi/ZZ8CzOaXBkxyKxNw@x1-carbon/ the link must be reset to wake the device then enumerate/validate it before removing it].  Several kernel developers believe that [https://lore.kernel.org/linux-scsi/ZZ8HjQXC3vp2lCuv@x1-carbon/ mixing SCSI pass-through commands (from hdparm) and commands submitted by the sd driver (from sysfs) is unsupported/undefined behavior].
 +
 
 +
--[[User:Kevinoid|Kevinoid]] ([[User talk:Kevinoid|talk]]) 02:12, 11 January 2024 (CET)

Latest revision as of 02:12, 11 January 2024

Recent Ubuntu versions

I think, it must be mentioned that hotswapping Ultrabay devices using recent distros is by far not that hard as before. I'm using Ubuntu 9.04 on Z61m and in my case hotswapping Ultrabay DVD-RW works out-of-the-box without any scripts or whatsoever. The article however suggests that one always needs some ejecting scripts which might confuse certain users. So it would be nice to add something like: "If you are using Ubuntu *.** everything should work out-of-the-box"

--Bombenbach 12:01, 9 August 2009 (UTC)

Really? Did you try to swap out a Ultrabay device with mounted filesystem? Good luck! The udev handler and eject script are there for a reason. By default no action is taken when you pull out a device, which can cause real problems if not handled properly.

--Tonko 09:31, 10 August 2009 (UTC)

Well, actually I couldn't imagine that someone would like to pull out an Ultrabay device with mounted file system. As far a usb flash drives are concerned, you won't do that either, right? My point was, that if the file system is properly unmounted, I can simply pull my Ultrabay DVD-RW out without any freezes or crashes. And when I put it back again, the drive is automatically recognized by Ubuntu so that I can use it. I don't have an Ultrabay HDD, but I assume that if it works with DVD-RW it also should work with HDD. Correct me if I'm wrong. If the sole purpose of eject script is hotswapping Ultrabay devices with mounted filesystem then I still think that it would be nice to point it out in the article.

--Bombenbach 07:52, 11 August 2009 (UTC)

By default on most modern distributions based on a recent kernel with libata, the libata driver gets to cleanup the mess after the fact, if you pull out an ultrabay device without first

  • unmounting the filesystem
  • powering down the device

You may be lucky, or you might end up with a hung system, corrupted filesystem, etc. Your choice.

There is work going on upstream to resolve this with DeviceKit-disks, but that depends on a patch to the Linux kernel, which has not made it in yet, since right now there is no correlation between the udev event and the actual Bay device, and since you can have multiple Bay devices (in fact your ThinkPad likely has 3) this correlation is needed, otherwise DeviceKit-disks would need to know about every single Laptop out there and the mapping between the Bay numbering and the actual devices (something the kernel can easily just provide instead).

Here is a Feature request against DeviceKit-disks that provides some status information http://bugs.freedesktop.org/show_bug.cgi?id=23110

--Tonko 09:07, 11 August 2009 (UTC)

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 A20m, A20p, A21e, A21m, A21p, A22e, A22m, A22p, 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_248a A30, A30p, A31, A31p Intel 82801CAM IDE U100 (rev 2) /org/freedesktop/Hal/devices/pci_8086_248a_scsi_host_scsi_device_lun0_0
/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

lshal of my A31: http://nopaste.org/p/a4p6x9tSob

Thanks! If I understand the output correctly you have one Toshiba Combo DVD-ROM/CD-RW R2002 in one ultrabay connected as slave to the primary IDE controller, and one Toshiba DVD-ROM C2512 in the second ultrabay connected as master to the secondary IDE controller. Can you confirm? I have added it to the table.


I have a Thinkpad T43 and I found out from my lshal output that I had to use parent device: pci_8086_2653_scsi_host_0_scsi_device_lun0 instead of pci_8086_2653_scsi_host_scsi_device_lun0 (notice the added 0). This is the ultrabay, however, the internal disk still use the "original" parent device (the one without the 0). I think this information should be added to the table. Specs: Thinkpad T43 (machine type 2668), Mandriva One 2009.1, haldaemon 0.5.12

Thanks, it is possible that you have AHCI mode disabled in the BIOS for your HDD? --Tonko 11:00, 31 July 2009 (UTC)

Thinkpad T510

The T510 uses the Arrandale chipset, or "Intel Corporation 5 Series/3400 Series Chipset". This seems to work for me:

        <!-- Lenovo ThinkPad T510 -->
        <match key="/org/freedesktop/Hal/devices/computer:system.hardware.version" contains_outof="T510">
          <match key="storage.bus" string_outof="pci;scsi">
            <match key="info.parent" string="/org/freedesktop/Hal/devices/pci_8086_3b2f_scsi_host_0_scsi_device_lun0">
              <merge key="storage.hotpluggable" type="bool">true</merge>
            </match>
          </match>
        </match>

--Jicama 01:58, 7 November 2010 (UTC)

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 effect)"
    echo "    -b         Use beep for notification (-q has no effect)"
    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 undocked"
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 guaranteed 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)

get notify-send working

Hi there,

I've modified your ultrabay_eject script so that the notify-send is working for the user which is logged onto screen :0 for an unified diff see below, here is the whole modified script

  • whole script
#!/bin/bash

# Change the following DEVPATH= to match your system, if you want to run this directly instead of having it called by the udev eject script
# To find the right value, insert the UltraBay optical drive and run:
# udevadm info --query=path --name=/dev/sr0 | perl -pe 's!/block/...$!!'
if [ "$DEVPATH" = "" ]
then
   DEVPATH="/devices/pci0000:00/0000:00:1f.2/host1/target1:0:0/1:0:0:0"
fi

shopt -s nullglob
export DISPLAY=:0.0 # required for notify-send

DISP0_USER=`lastlog | grep "[[:space:]]:0" | awk '{ print $1 }'` # the [[:space:]] before the :0 is needed to exclude ipv6 adresses
DISP0_USER_HOME=`getent passwd ${DISP0_USER} | cut -d':' -f6`
export XAUTHORITY=${DISP0_USER_HOME}/.Xauthority # also required for notify-send

ULTRABAY_SYSDIR=/sys$DEVPATH

# Find generic dock interface for UltraBay
dock=$( /bin/grep -l ata_bay /sys/devices/platform/dock.?/type )
dock=${dock%%/type}
if [ -n "$dock" -a -d "$dock" ]; then
        logger ultrabay_eject starting eject of $dock
else
        logger ultrabay_eject cannot locate bay dock device
        notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Cannot locate bay dock device"
fi

# Umount the filesystem(s) backed by the given major:minor device(s)
unmount_rdev() { perl - "$@" <<'EOPERL'  # let's do it in Perl
        for $major_minor (@ARGV) {
                $major_minor =~ m/^(\d+):(\d+)$/ or die;
                push(@tgt_rdevs, ($1<<8)|$2);
        }
        # Sort by reverse length of mount point, to unmount sub-directories first
        open MOUNTS,"</proc/mounts" or die "$!";
        @mounts=sort { length($b->[1]) <=> length($a->[1]) } map { [ split ] } <MOUNTS>;
        close MOUNTS;
        foreach $m (@mounts) {
                ($dev,$dir)=@$m;
                next unless -b $dev;  $rdev=(stat($dev))[6];
                next unless grep($_==$rdev, @tgt_rdevs);
                system("umount","-v","$dir")==0  or  $bad=1;
                if ($bad == 1) {
                        system("logger","ultrabay_eject","ERROR unmounting",$dev,$dir);
                        system("notify-send -u critical -t 100000 \"Error unmounting $dir\" \"Unmounting of $dir on $dev failed!\"");
                } else {
                        system("logger","ultrabay_eject","unmounted",$dev,$dir);
                        system("notify-send -u normal -t 5000 \"Unmounted $dir\"");
                };
        }
        exit 1 if $bad;
EOPERL
}

# Get the UltraBay's /dev/foo block device node
ultrabay_dev_node() {
        UDEV_PATH="`readlink -e "$ULTRABAY_SYSDIR/block/"*`" || return 1
        UDEV_NAME="`udevadm info --query=name --path=$UDEV_PATH`" || return 1
        echo /dev/$UDEV_NAME
}

if [ $( cat $dock/docked ) == 0 ]; then
        logger ultrabay_eject dock reports empty
else 
	if [ -d $ULTRABAY_SYSDIR ]; then
		logger ultrabay_eject dock occupied, shutting down storage device $DEVPATH
		sync
		# Unmount filesystems backed by this device
		## This seems to be very inelegant and prone to failure
		unmount_rdev `cat $ULTRABAY_SYSDIR/block/*/dev     \
				  $ULTRABAY_SYSDIR/block/*/*/dev`  \
		|| {
			logger ultrabay_eject umounting failed
			echo 2 > /proc/acpi/ibm/beep  # triple error tone
			notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Please do not pull the device, doing so could cause file corruption and possibly hang the system. Unmounting of the filesystem on the ThinkPad Ultrabay device failed. Please put the eject leaver back in place, and try to unmount the filesystem manually. If this succeeds you can try the eject again"
			exit 1;
		}
		sync
		# Nicely power off the device
		DEVNODE=`ultrabay_dev_node` && hdparm -Y $DEVNODE
		# Let HAL+KDE notice the unmount and let the disk spin down
		sleep 0.5
		# Unregister this SCSI device:
		sync
		echo 1 > $ULTRABAY_SYSDIR/delete
	else
		logger ultrabay_eject bay occupied but incorrect device path $DEVPATH
		notify-send -u critical -t 100000 "ThinkPad Ultrabay eject failed" "Bay occupied but incorrect device path"
		echo 2 > /proc/acpi/ibm/beep  # triple error tone
		exit 1
	fi
fi

# We need sleep here so someone can disconnect the bay and the drive
sleep 1

# Turn off power to the UltraBay
logger ultrabay_eject undocking $dock
echo 1 > $dock/undock

# Tell the user we're OK
logger ultrabay_eject done
echo 12 > /proc/acpi/ibm/beep
notify-send -u normal -t 10000 "Safe to remove device" "The ThinkPad Ultrabay device can now safely be removed"

  • unified diff
--- ultrabay_eject.orig	2010-01-07 22:51:40.000000000 +0100
+++ ultrabay_eject	2010-01-07 22:54:55.000000000 +0100
@@ -10,6 +10,11 @@
 
 shopt -s nullglob
 export DISPLAY=:0.0 # required for notify-send
+
+DISP0_USER=`lastlog | grep "[[:space:]]:0" | awk '{ print $1 }'` # the [[:space:]] before the :0 is needed to exclude ipv6 adresses
+DISP0_USER_HOME=`getent passwd ${DISP0_USER} | cut -d':' -f6`
+export XAUTHORITY=${DISP0_USER_HOME}/.Xauthority # also required for notify-send
+
 ULTRABAY_SYSDIR=/sys$DEVPATH
 
 # Find generic dock interface for UltraBay

i hope this is useful to other users as well --Roo 22:19, 7 January 2010 (UTC)

A warning about sysfs docked

A note to script writers/users: The docked sysfs attribute can be unreliable. Be sure the script fails safely if it reports 0 when there are docked devices.

--Kevinoid (talk) 20:45, 14 March 2017 (CET)

hdparm -Y removed from script for Ultrabay eject

Previously the Script for Ultrabay eject invoked hdparm -Y before echo 1 > $ULTRABAY_SYSDIR/delete. From the comment, it appears that the intent was to spin down the drive before deleting the ATA device. Unfortunately, this is both unnecessary, since it is done automatically by the kernel, and counterproductive, since the link must be reset to wake the device then enumerate/validate it before removing it. Several kernel developers believe that mixing SCSI pass-through commands (from hdparm) and commands submitted by the sd driver (from sysfs) is unsupported/undefined behavior.

--Kevinoid (talk) 02:12, 11 January 2024 (CET)