How to hotswap Ultrabay devices

From ThinkWiki
Revision as of 13:20, 19 May 2007 by Whoopie (Talk | contribs) (Scripts for hotswapping: give file names more clear names)

Jump to: navigation, search

The following discusses hotswap (AKA "hotplug") of devices in the UltraBay.

When using the ide-disk driver

The following applies if you use the ide-disk driver for the UltraBay device.

Hotswapping is supposed to be supported as well, using either hdparm/Debian hotswap or lt_hotswap to (un)register IDE devices. The latter is the recommended method with kernels from 2.6, since it will leave DMA working. However, for recent models (R52, T43, X41, Z60 and later) no method is known to work while maintaining DMA support; see Problems with SATA and Linux.

Only IDE devices (HDD's, optical drives, zip drives) require special treatment - batteries, floppies and other devices can just be pulled from the bay, provided they are not mounted or in use at the time. However, you should still power them down first using the ibm-acpi eject function.

The ibm-acpi kernel module has an eject function (# echo eject > /proc/acpi/ibm/bay). This only manages the ACPI calls to power down the device and the bay. It does not actually unregister the device from the IDE driver. # cat /proc/acpi/ibm/bay shows "unoccupied" unless an IDE device is present, but the eject function still works and should still be used.

To unregister the device, you can either use the Debian hotswap package, or lt_hotswap.

Debian hotswap also allows the drive to be swapped as a normal user by default, which is useful. You should use hotswap to unregister the device and then # echo eject > /proc/acpi/ibm/bay. However, if you use this method on a 2.6 kernel, you will lose DMA support for the reinserted drive. This is due to kernel issues. This method was reported to work on a ThinkPad T23 (kernels 2.6.8.1, 2.6.14.2 and 2.6.15-arch) and T42 (kernel 2.6.13), but fails on a ThinkPad T43 (kernel 2.6.14.3).

lt_hotswap is now the recommended method to un- and reregister the IDE device. It installs as a kernel module and has support for automatically unregistering (if loaded with the auto_eject=1 option) the device when the eject event is generated by ibm-acpi. It will leave DMA support intact. It has supported to work on a ThinkPad T22 and T40 and should work with many other models (but not recent models which require the ata_piix driver for disk DMA support). With the lt_hotswap kernel module loaded, run: # modprobe -r ide_cd && modprobe -r cdrom && echo "MSTR eject" > /proc/acpi/lths

HAL support

HAL support also can also be configured To do so, create the file /etc/hal/fdi/information/10-ultrabay.fdi as follows:

<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- -->

<deviceinfo version="0.2">
  <device>

    <!-- UltraBay Devices -->
    <match key="storage.bus" string="ide">
      <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_24ca_ide_1_0">
        <merge key="storage.hotpluggable" type="bool">true</merge>
      </match>
    </match>

  </device>
</deviceinfo>

For more details see HAL section for ata driver.

When using the ata_piix driver

The following applies when using the ata_piix driver, which is necessary for many recent ThinkPad models that use an Intel ICH6-M controller. See also Problems with SATA and Linux.

Mainline kernels before 2.6.18 cannot reliably recognize newly (re-)inserted UltraBay drives without a reboot. There are experimental hotplug patches against pre-2.6.18 mainline kernels here.

  • Confirmed to work on

For 2.6.18 kernels, or older kernels that were patched to support ata_piix hotplug (don't try it otherwise!), one can issue the following after inserting an UltraBay drive to rescan the port:

# echo 0 0 0 >  /sys/class/scsi_host/host1/scan

The inserted drive should now be recognized by the kernel, and appropriate /dev/* entries created automatically (e.g., by udev).

You can safely shut down the drive by issuing the following (this works with all recent mainline kernels):

# echo 1 > /sys/class/scsi_device/1\:0\:0\:0/device/delete
# echo eject >  /proc/acpi/ibm/bay

The drive can now be ejected.

Scripts for hotswapping

The following scripts and acpid daemon configuration files do the following:

  • Automatically unmounts the relevant filesystems and power off the UltraBay when the UltraBay eject lever is released. Screams if some filesystem can't be unmounted.
  • Rescans the UltraBay port when then UltraBay eject lever is pushed back in.

They assumes you're using the ata_piix driver with an appropriate kernel (see above).

Create /usr/local/sbin/ultrabay_insert with permissions 755:

#!/bin/bash
echo 12 > /proc/acpi/ibm/beep
sync
echo 0 0 0 > /sys/class/scsi_host/host1/scan

Create /usr/local/sbin/ultrabay_eject with permissions 755:

#!/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)
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;
	}
	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="`udevinfo -q name -p $UDEV_PATH`" || return 1
	echo /dev/$UDEV_NAME
}

if [ -d $ULTRABAY_SYSDIR ]; then
	sync
	# Unmount filesystems backed by this device
	unmount_rdev `cat $ULTRABAY_SYSDIR/block\:*/dev     \
	                  $ULTRABAY_SYSDIR/block\:*/*/dev`  \
	|| {
		echo 10 > /proc/acpi/ibm/beep;  # error tone
		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
fi
sync
# Turn off power to the UltraBay:
if [ -d /sys/devices/platform/bay.0 ]; then
	echo 1 > /sys/devices/platform/bay.0/eject
else
	echo eject > /proc/acpi/ibm/bay
fi
# Tell the user we're OK
echo 12 > /proc/acpi/ibm/beep

Create /etc/acpi/events/ultrabay-insert:

event=ibm/bay MSTR 00000001 00000000
action=/usr/local/sbin/ultrabay_insert

Create /etc/acpi/events/ultrabay-eject:

event=ibm/bay MSTR 00000003 00000000
action=/usr/local/sbin/ultrabay_eject

Restart acpid.

HAL support

Many programs, KDE included, rely on HAL to get notifications and information about device hotplugging. You need to tell HAL that devices connected the UltraBay port are hotpluggable. To do so, create the file /etc/hal/fdi/information/10-ultrabay.fdi as follows:

<?xml version="1.0" encoding="UTF-8"?> <!-- -*- SGML -*- --> 

<deviceinfo version="0.2">
  <device>

    <!-- UltraBay Devices -->
    <match key="storage.bus" string="scsi">
      <match key="storage.physical_device" string="/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0">
        <merge key="storage.hotpluggable" type="bool">true</merge>
      </match>
    </match>

  </device>
</deviceinfo>

Details

By default, HAL doesn't know that UltraBay devices are hotpluggable:

# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0
# UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed
# hal-get-property --udi $UDI --key block.device
/dev/sdb
# hal-get-property --udi $UDI --key storage.hotpluggable
false

After creating /etc/hal/fdi/information/10-ultrabay.fdi as above and re-plugging the device, it will get marked correctly:

# PHYSDEV=/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0
# UDI=`hal-find-by-property --key storage.physical_device --string $PHYSDEV` || echo Failed
# hal-get-property --udi $UDI --key block.device
/dev/sdb
# hal-get-property --udi $UDI --key storage.hotpluggable
true

The string "8086_2653" gives the PCI ID of the Intel 82801FBM southbridge. If your model has a different southbridge, or the UltraBay is attached to a different port, then you can find the appropriate storage.physical_device value by finding out the block device of the currently running UltraBay device (/dev/sdb in the following example) and then running:

# DEVICE=/dev/sdb
# UDI=`hal-find-by-property --key block.device --string $DEVICE` || echo Failed
# hal-get-property --udi $UDI --key storage.physical_device
/org/freedesktop/Hal/devices/pci_8086_2653_scsi_host_scsi_device_lun0

If you have a different storage.physical_device value, please report your findings.

Known South Bridge PCI IDs
ID ThinkPad model South Bridge chip
8086_248a 2366-83U (T30) Intel 82801CAM IDE U100 (rev 2)
8086_2653 2525FAG (X41) Intel 82801FBM
8086_24ca 237358U (T40) Intel 82801DBM (ICH4-M)
8086_27c4 X60 Intel 82801GBM (ICH7 Family)

Other comments

If you are hot-swapping a hard disk on a disk tray, make sure the disk does not have a password set, otherwise it will not be recognized on reinsertion.