It kind of needs to be enabled in Linux because the ASMedia firmware isn't really spec-compliant enough (and kernel devs refuse to ignore that informational flaw).
You don't even need to do zero check like that to confirm TRIM is working (some TRIM implementation doesn't always guarantee (fully) "read zero after TRIM" anyway).
First of all install the package sg3-utils (or sg3_utils in some distros) and use `sg_vpd` to check whether the firmware supports TRIM:
Code: Select all
[tom@archlinux ~]$ sudo sg_vpd -p bl /dev/sdc
Block limits VPD page (SBC):
Write same non-zero (WSNZ): 0
Maximum compare and write length: 0 blocks [Command not implemented]
Optimal transfer length granularity: 1 blocks
Maximum transfer length: 65535 blocks
Optimal transfer length: 65535 blocks
Maximum prefetch transfer length: 65535 blocks
Maximum unmap LBA count: 4194240
Maximum unmap block descriptor count: 1
Optimal unmap granularity: 1 blocks
Unmap granularity alignment valid: false
Unmap granularity alignment: 0 [invalid]
Maximum write same length: 0 blocks [not reported]
Maximum atomic transfer length: 0 blocks [not reported]
Atomic alignment: 0 [unaligned atomic writes permitted]
Atomic transfer length granularity: 0 [no granularity requirement
Maximum atomic transfer length with atomic boundary: 0 blocks [not reported]
Maximum atomic boundary size: 0 blocks [can only write atomic 1 block]
Code: Select all
[tom@archlinux ~]$ sudo sg_vpd -p lbpv /dev/sdc
Logical block provisioning VPD page (SBC):
Unmap command supported (LBPU): 1
Write same (16) with unmap bit supported (LBPWS): 0
Write same (10) with unmap bit supported (LBPWS10): 0
Logical block provisioning read zeros (LBPRZ): 0
Anchored LBAs supported (ANC_SUP): 0
Threshold exponent: 0 [threshold sets not supported]
Descriptor present (DP): 0
Minimum percentage: 0 [not reported]
Provisioning type: 0 (not known or fully provisioned)
Threshold percentage: 0 [percentages not supported]
If you see "Maximum unmap LBA count" not being 0 and "Unmap command supported (LBPU)" being one, the firmware has TRIM support built in it.
Code: Select all
[tom@archlinux ~]$ sudo sg_readcap -l /dev/sdc
Read Capacity results:
Protection: prot_en=0, p_type=0, p_i_exponent=0
Logical block provisioning: lbpme=0, lbprz=0
Last LBA=468862127 (0x1bf244af), Number of logical blocks=468862128
Logical block length=512 bytes
Logical blocks per physical block exponent=0
Lowest aligned LBA=0
Hence:
Device size: 240057409536 bytes, 228936.6 MiB, 240.06 GB
With sg_readcap -l, you can find out the "Logical block length". Multiply it with "Maximum unmap LBA count" you get the maxium bytes that a single SCSI UNMAP (which is translated to ATA TRIM by the adapter) can cover. Note that the value is hard-coded in the adapter, but the value should be safe even with the oldest SSD that supports TRIM (with the above case it's like a minimum that a TRIM command should be able to support anyway, IIRC).
Also see that lbpme=0 here. This is the flaw I mentioned. If it's 1 you do not need to enable TRIM (or more precisely, unmap / discard, the SCSI / OS level terms) manually. I have yet to see any TRIM supporting adapter with firmware that reports this correctly. So I'm intrigued in whether what @HawaiianPi said (that the "ELUTENG blue adapter supports TRIM on Linux OOTB") is real. Anyway, here's the code:
https://github.com/raspberrypi/linux/bl ... sd.c#L2349
https://github.com/raspberrypi/linux/bl ... sd.c#L2979
https://github.com/raspberrypi/linux/bl ... sd.c#L2884
EDIT: I then saw another of his posts talking about the need of changing provisioning_mode
Btw, unless I remember it wrongly, disabling UAS doesn't prevent discard/UNMAP/TRIM from working or being enabled by default (if the firmware fulfills the "requirements" of the scsi disk driver, that is). I glimpsed scsiglue.c in the usb-storage driver again and didn't notice such code either. (Although without UAS NCQ isn't supported so the performance impact might be heavier; something like that I guess.) But maybe I just forgot something.
Code: Select all
[root@archlinux ~]# find /sys/ -name provisioning_mode -exec grep . {} + | sort
/sys/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/host6/target6:0:0/6:0:0:0/scsi_disk/6:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:14.0/usb3/3-5/3-5:1.0/host8/target8:0:0/8:0:0:0/scsi_disk/8:0:0:0/provisioning_mode:full
/sys/devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/provisioning_mode:writesame_16
The above sysfs files (which are virtual/volatile) reports whether discard is enabled/allowed for the respective drive and can be used to change the setting as well. You can install and use lsscsi (or maybe even udevadm) to find out which drive each of their paths is referring to:
Code: Select all
[root@archlinux ~]# lsscsi
[0:0:0:0] disk ATA SPCC Solid State 4A0 /dev/sda
[1:0:0:0] cd/dvd PIONEER BD-RW BDR-S08 1.10 /dev/sr0
[6:0:0:0] disk ASMT 2115 0 /dev/sdb
[7:0:0:0] disk PNY CS90 0 240GB SSD 0 /dev/sdc
[8:0:0:0] disk SPCC Sol id State Disk 0 /dev/sdd
[root@archlinux ~]# fstrim /
fstrim: /: the discard operation is not supported
[root@archlinux ~]# findmnt /
TARGET SOURCE FSTYPE OPTIONS
/ /dev/sdc2 f2fs rw,relatime,lazytime,background_gc=on,discard,no_heap,user_xattr,inline_xattr,acl,inline_data,inline_dentry,flush_merge,extent_cache,mode=adaptive,active_logs=6,alloc_mode=default,fsync_m
[root@archlinux ~]# echo unmap > /sys/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/provisioning_mode
[root@archlinux ~]# cat /sys/devices/pci0000:00/0000:00:14.0/usb3/3-4/3-4:1.0/host7/target7:0:0/7:0:0:0/scsi_disk/7:0:0:0/provisioning_mode
unmap
[root@archlinux ~]# echo $((4194240*512))
2147450880
[root@archlinux ~]# cat /sys/block/sdc/queue/discard_max_bytes
4294966784
[root@archlinux ~]# echo $((4194240*512)) > /sys/block/sdc/queue/discard_max_bytes
[root@archlinux ~]# cat /sys/block/sdc/queue/discard_max_bytes
2147450880
[root@archlinux ~]# fstrim /
[root@archlinux ~]#
The settings are volatile so you'll need to write udev rules to make them persistent. I'm not gonna cover it here.
Note that discard-upon-deletion requires you to have the filesystem mounted with the option discard, although some do that by default (e.g. f2fs), while fstrim works as long as you done changing the scsi/block-level settings.