Difference between revisions of "Talk:How to hotswap Ultrabay devices"
(→one nit about ultrabay_close script / patch against 2.6.17 available) |
(→hdparm -Y removed from script for Ultrabay eject: new section) |
||
(63 intermediate revisions by 22 users not shown) | |||
Line 1: | Line 1: | ||
− | I | + | =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" | ||
− | + | --[[User:Bombenbach|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. | |
− | + | --[[User:Tonko|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. |
− | + | --[[User:Bombenbach|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 | ||
− | -- | + | --[[User:Tonko|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. | |
+ | <pre> | ||
+ | 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) | ||
+ | </pre> | ||
− | == | + | {| 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 | ||
− | + | 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. | |
− | |||
− | + | 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? | |
+ | --[[User:Tonko|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: | |
− | + | <pre> | |
+ | <!-- 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> | ||
+ | </pre> | ||
+ | --[[User:Jicama|Jicama]] 01:58, 7 November 2010 (UTC) | ||
− | --[[User: | + | = 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|Please test on difrent models}} | ||
+ | |||
+ | 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 | ||
+ | } | ||
+ | |||
+ | 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" | ||
+ | </pre> | ||
+ | |||
+ | 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<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) | ||
+ | |||
+ | == 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 | ||
+ | <pre> | ||
+ | #!/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" | ||
+ | |||
+ | </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> | ||
+ | |||
+ | 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
Contents
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)
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 :)
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.