Trim and SSD with USB 3.0 enclosure does not work - UASP not supported?

Solution 1:

This is a software issue, Linux does not seem to currently support TRIM through USB. The problem is that USB storage devices employ the SCSI command set, whereas the SSD drive implements the ATA command set. The USB enclosure has to provide a translator between these command sets. The operation called TRIM in ATA is called UNMAP in SCSI and DISCARD in the Linux kernel. When Linux receives the command to trim a device, it looks up the correct command to be sent to the device. As USB storage devices look like SCSI disks, Linux tries to use UNMAP or a couple of other possible SCSI commands. In principle, the translator in the USB enclosure could often translate UNMAP requests to the corresponding ATA TRIM, although there are probably tricky cases. In practice, the enclosures don't do this, and they indicate instead that the device does not support UNMAP. However, many enclosures implement a SCSI command to issue ATA commands directly to the device. It is called ATA passthrough. There is a standard command to do this, but some enclosures have a proprietary command instead. In fact, hdparm -I uses ATA passthrough to get information from the device. The same passthrough could be used to issue TRIMs directly to the device, but the Linux driver does not currently do that. It would have to detect that a SCSI disk is actually a SCSI-to-ATA translator that supports ATA passthrough and use the passthrough for DISCARDs instead of the native SCSI commands.

Solution 2:

This question deserves an updated answer now that there are USB enclosures on the market that support trim. For example if your enclosure uses the JMICRON JMS583 chip then it supports trim.

I am going to only include the steps required to get it to work if it is supported, but if you want a more detailed walk-through see the source link below.

  1. Get the vendor and product ids from lsusb
  2. Create /etc/udev/rules.d/50-usb-ssd-trim.rules with the following content, but change the vendor and product ids to match the ones found in step 1:
ACTION=="add|change", ATTRS{idVendor}=="152d", ATTRS{idProduct}=="0583", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
  1. Reload the udev configuration sudo service udev force-reload
  2. Make sure you don't have the USB enclosure mounted and then replug the USB enclosure.
  3. You can check if trim is supported with lsblk --discard /dev/sda

See: https://www.glump.net/howto/desktop/enable-trim-on-an-external-ssd-on-linux

Solution 3:

Your SSD reports to hdparm to support TRIM (hdparm -I = Request identification info directly from the drive).

TRIM however, is controlled by the drive controller.

It is quite likely that the USB3 harddiskcontroller of the external HDD closure doesn't support TRIM (most external controllers don't).

In that case you won't get any TRIM capabilities even if your SSD does support it.

Solution 4:

If UNMAP is not translated correctly by your enclosure you can at least manually trim the whole drive using hdparm (this uses the ata-passthrough of the SCSI protocol and works fine on my UASP hdd dock). But you have to calculate the sectors manually because hdparm only supports trimming 65535 sectors at a time. I have written a short script to do the math:

#!/usr/bin/env python3

import sys

remaining = int(sys.argv[1])
i = 0

while remaining > 0:
    add = min(65535, remaining)
    print("%d:%d" % (i, add))
    remaining -= add
    i += add

Save it as sectors.py and do chmod +x sectors.py. It yields a list of sector-blocks usable with hdparm --trim-sector-ranges-stdin. Now execute hdparm -I /dev/sdX (as root) and hold out for a line that looks like:

LBA48  user addressable sectors:   62533296

This is the devices sector count (as you could calculate this is a ~32 GB SSD I frequently use for testing).

Copy the number to the following command:

./sectors.py SECTOR_COUNT | sudo hdparm --trim-sector-ranges-stdin --please-destroy-my-drive /dev/sdX

WARNING: This will erase the WHOLE DRIVE!

After it finished, run sync and wait some seconds. Now you can re-read the partition table with hdparm -z /dev/sdX or simply power-cycle the device. Congratulations, you have a "fresh" SSD now.