TRIM (ATA) bzw. UNMAP (SCSI/USB) erlaubt dem Betriebssystem, der SSD mitzuteilen, welche Blöcke nicht mehr genutzt werden. Ohne TRIM muss die SSD beim Schreiben erst löschen – was sie über Zeit messbar langsamer macht.
USB-SATA-Bridges wie der JMicron JMS567 melden dem Kernel fälschlicherweise, TRIM nicht zu unterstützen (DISC-MAX=0), obwohl die angeschlossene SSD es kann. Der Grund: der Treiber wählt den falschen SCSI-Provisioning-Modus. Das lässt sich per udev-Regel dauerhaft korrigieren, ohne den Kernel-Treiber zu patchen.
| Begriff | Bedeutung |
|---|---|
| TRIM / UNMAP | Befehl, mit dem das OS der SSD freigegebene Blöcke meldet – hält die Schreibperformance langfristig stabil |
| provisioning_mode | Kernel-Attribut am SCSI-Gerät: full = kein TRIM, unmap = TRIM aktiv |
| udev-Regel | Wird beim Einstecken des Geräts ausgeführt und setzt provisioning_mode automatisch |
| fstrim.timer | Systemd-Timer, der wöchentlich fstrim auf allen gemounteten Dateisystemen ausführt |
152d:3562). Andere Bridges (JMS578, ASMedia ASM1153, Realtek RTL9210) können dieselbe Symptomatik zeigen – die udev-Regel funktioniert analog, nur Vendor- und Product-ID unterscheiden sich.
Zuerst Vendor-ID und Product-ID der USB-SATA-Bridge ermitteln:
lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub Bus 002 Device 002: ID 152d:3562 JMicron Technology Corp. JMS567 SATA 6Gb/s bridge
Das Format ist immer VendorID:ProductID – hier 152d (JMicron) und 3562 (JMS567). Diese beiden Werte kommen in der udev-Regel zum Einsatz.
Welches Block-Device die Bridge erzeugt hat:
lsblk -o NAME,MODEL,TRAN,SIZE
NAME MODEL TRAN SIZE
sda Samsung SSD 870 usb 931G
├─sda1 512M
└─sda2 930G
lsblk -D zeigt die Discard-Fähigkeiten jedes Block-Devices. Entscheidend ist DISC-MAX: ist der Wert 0B, erkennt Linux kein TRIM.
lsblk -D
NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda 0 0B 0B 0
├─sda1 0 0B 0B 0
└─sda2 0 0B 0B 0
DISC-MAX=0B und DISC-GRAN=0B bedeuten: der Kernel glaubt, das Gerät unterstützt kein TRIM. Nach dem Fix sollten beide Werte größer null sein.
Die Regel setzt provisioning_mode=unmap immer dann, wenn genau dieses Gerät (per Vendor/Product-ID) als SCSI-Disk erkannt wird. Sie ist damit gerätespezifisch und beeinflusst keine anderen USB-Geräte.
ACTION=="add|change", ATTRS{idVendor}=="152d", ATTRS{idProduct}=="3562", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"
10-jmicron-trim.rules so lassen – niedrige Präfix-Zahl (10) stellt sicher, dass die Regel früh geladen wird, bevor andere Regeln das Gerät konfigurieren.
lsusb (Schritt 1) entsprechend anpassen. Alle Werte sind hexadezimal und vierstellig, z. B. 174c:55aa für ASMedia ASM1153.
# udev-Regeln neu laden sudo udevadm control --reload-rules # Ereignisse für alle vorhandenen Geräte erneut auslösen sudo udevadm trigger
Direkt prüfen, ob die Regel greift:
cat /sys/block/sda/device/scsi_disk/*/provisioning_mode
unmap
lsblk -D
NAME DISC-ALN DISC-GRAN DISC-MAX DISC-ZERO
sda 0 4K 4G 0
├─sda1 0 4K 4G 0
└─sda2 0 4K 4G 0
DISC-GRAN=4K und DISC-MAX=4G bedeuten: TRIM ist aktiv. Die SSD meldet ihre tatsächlichen Discard-Grenzen an den Kernel.
hdparm: sudo hdparm -I /dev/sda | grep -i trim – sollte Data Set Management TRIM supported zeigen.
Einmalig testen, ob der Kernel wirklich TRIM-Befehle an die SSD senden kann:
sudo fstrim -v /
/: 690.2 MiB (723771392 bytes) trimmed
Alle gemounteten Dateisysteme auf einmal trimmen:
sudo fstrim -av
discard in /etc/fstab (kontinuierliches TRIM) vermeiden – sie erzeugt viele kleine SCSI UNMAP-Befehle und kann USB-Bridges mit begrenztem Command-Queuing ausbremsen. Periodisches TRIM via fstrim.timer ist die bessere Wahl.
Systemd bringt einen fertigen Timer mit, der einmal pro Woche fstrim -av aufruft:
sudo systemctl enable --now fstrim.timer
systemctl status fstrim.timer systemctl list-timers fstrim.timer
sudo systemctl start fstrim.service lässt er sich manuell auslösen.
Das Problem tritt bei mehreren verbreiteten Chips auf. Die udev-Regel ist identisch – nur die IDs ändern sich:
| Chip | Vendor:Product | Verbreitung |
|---|---|---|
| JMicron JMS567 | 152d:3562 | Häufig in günstigen 2,5″-Gehäusen |
| JMicron JMS578 | 152d:0578 | Neuere JMicron-Generation |
| ASMedia ASM1153 | 174c:55aa | In vielen Raspberry Pi-Gehäusen |
| ASMedia ASM2362 | 174c:2362 | NVMe-Adapter mit USB 3.2 |
| Realtek RTL9210 | 0bda:9210 | Neuere High-Speed-Adapter |
# Alle USB-Storage-Geräte mit IDs anzeigen lsusb | grep -i "storage\|jmicron\|asmedia\|realtek\|seagate\|western" # Detailinfo zum Block-Device (zeigt auch USB-IDs) udevadm info --query=all --name=/dev/sda | grep -E "ID_VENDOR|ID_MODEL|idVendor|idProduct"
| Problem | Lösung |
|---|---|
| DISC-MAX bleibt 0B nach Regel-Reload | Regel-Datei auf Syntaxfehler prüfen: udevadm test $(udevadm info -q path -n /dev/sda) – Ausgabe zeigt, ob die Regel matcht und was gesetzt wird |
| provisioning_mode nicht schreibbar | Kernel-Modul sg fehlt: sudo modprobe sg dann Regel erneut anwenden |
| fstrim meldet "Operation not supported" | Das Dateisystem unterstützt TRIM nicht (z. B. FAT32). ext4, f2fs, btrfs, xfs und NTFS (ntfs3) unterstützen es; FAT32/exFAT nicht |
| fstrim: "Device or resource busy" | Gerät ist intensiv in Nutzung. Zu einem ruhigeren Zeitpunkt erneut versuchen oder fstrim.timer übernehmen lassen |
| Nach Neustart ist DISC-MAX wieder 0 | Regel wird nicht geladen: Datei liegt falsch (ls /etc/udev/rules.d/10-jmicron*) oder Schreibfehler im Dateinamen (.rules fehlt) |
| Gerät ist an anderem Bus als erwartet | Regel nutzt ATTRS{} (Eltern-Attribute) – funktioniert unabhängig vom USB-Port. Kein Anpassen nötig beim Umstecken |
# Regel testen ohne Neustart (zeigt alle Attribute und Aktionen)
sudo udevadm test $(udevadm info -q path -n /dev/sda) 2>&1 | grep -E "provisioning|TRIM|match|run"