Skip to content

Instantly share code, notes, and snippets.

@satmandu
Last active March 31, 2024 00:54
Show Gist options
  • Save satmandu/fe9d9f446f7e7409712a4b4789d24b23 to your computer and use it in GitHub Desktop.
Save satmandu/fe9d9f446f7e7409712a4b4789d24b23 to your computer and use it in GitHub Desktop.
Detect and enable trim for usb-connected sata/nvme drives in initramfs/initrd, ideally before zfs modules load.
#!/bin/bash
# This goes in /usr/share/initramfs-tools/hooks/usbtrim
case $1 in
prereqs)
echo "udev"
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
mkdir -p $DESTDIR/lib/udev/rules.d/
testscsi=$(for devlink in /dev/disk/by-id/scsi*; do readlink -f "${devlink}" | sed 's/.*sd//'| cut -c1; done | sort -u)
[[ "$testscsi" == "/" ]] && test="" || test+="${testscsi} "
testata=$(for devlink in /dev/disk/by-id/ata*; do readlink -f "${devlink}" | sed 's/.*sd//'| cut -c1; done | sort -u)
[[ "$testata" == "/" ]] && test+="" || test+="${testata} "
testusb=$(for devlink in /dev/disk/by-id/usb*; do readlink -f "${devlink}" | sed 's/.*sd//'| cut -c1; done | sort -u)
[[ "$testusb" == "/" ]] && test+="" || test+="${testusb} "
[[ "$test" == "/" ]] && exit 0
[[ -z "$test" ]] && exit 0
for disk in $test; do
echo "checking sd${disk} for TRIM support."
if (sg_readcap -l /dev/sd"${disk}" | grep -q lbpme=0) ; then
echo "Trim not detected by kernel on /dev/sd${disk}."
if (sg_vpd -a /dev/sd"${disk}" | grep -q "(LBPU): 1") ; then
echo "UAS trim available on /dev/sd${disk}."
grep -q -s Created /etc/udev/rules.d/10-usb-trim.rules || (echo "# Created by `basename \"$0\"` in `dirname \"$0\"`" | tee /etc/udev/rules.d/10-usb-trim.rules)
grep -q -s Created $DESTDIR/lib/udev/rules.d/10-usb-trim.rules || (echo "# Created by `basename \"$0\"` in `dirname \"$0\"`" | tee $DESTDIR/lib/udev/rules.d/10-usb-trim.rules)
idVendor=$(lsusb -D $(udevadm info --path $(udevadm info -q path /dev/sd"${disk}" | rev | cut -d'/' -f7- | rev) | grep DEVNAME | cut -d = -f 2) 2>/dev/null | grep idVendor | awk '{print $2}' | cut -c 3-)
idProduct=$(lsusb -D $(udevadm info --path $(udevadm info -q path /dev/sd"${disk}" | rev | cut -d'/' -f7- | rev) | grep DEVNAME | cut -d = -f 2) 2>/dev/null | grep idProduct | awk '{print $2}' | cut -c 3-)
echo "ACTION==\"add|change\", ATTRS{idVendor}==\"$idVendor\", ATTRS{idProduct}==\"$idProduct\", SUBSYSTEM==\"scsi_disk\", ATTR{provisioning_mode}=\"unmap\"" | tee -a /etc/udev/rules.d/10-usb-trim.rules
echo "ACTION==\"add|change\", ATTRS{idVendor}==\"$idVendor\", ATTRS{idProduct}==\"$idProduct\", SUBSYSTEM==\"scsi_disk\", ATTR{provisioning_mode}=\"unmap\"" | tee -a $DESTDIR/lib/udev/rules.d/10-usb-trim.rules
if grep -q full /sys/block/sd"${disk}"/device/scsi_disk/*/provisioning_mode; then
echo "full on /dev/sd${disk}."
elif grep -q unmap /sys/block/sd"${disk}"/device/scsi_disk/*/provisioning_mode; then
echo "unmap already set on /dev/sd${disk}."
else
echo "enabling TRIM on /dev/sd${disk}."
echo "unmap" | tee /sys/block/sd"${disk}"/device/scsi_disk/*/provisioning_mode
fi
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment