I'm trying to understand TRIM, such as is used on SSDs. As a first step towards this, I'm trying to do a rudimentary backport to a 5.2 derivative I'm using - nothing teaches a thing like implementing it. I found wd_trim() in 9.2's wd.c and had a stab at integrating a form of it into my kernel.
It doesn't work, as you can probably infer from my writing this mail. Userland issues the ioctl I'm using as aan early-stage API, printfs indicate that my kernel code is running, and...it times out. I'm writing to ask if there's anyone who knows TRIM well enough to have a stab at telling what's wrong and is willing to try. Anyone not interested in details can stop reading now without loss; the rest of this mail details what I've done and what I got. I've presumably made some mistake somewhere, but it's not clear to me. Here's the code I dropped into wdioctl(), adapted from 9.2's wd_trim(). I also lifted ataparams fields 129 through 208 from 9.2, including things such as ATA_SUPPORT_DSM_TRIM. (5.2 has all those fields as a reserved [80] array.) case ATAIOCTRIM: { unsigned char rq[512]; struct ata_command cmd; int rv; if (! (flag & FWRITE)) return(EBADF); if (! (wd->sc_params.atap_ata_major & WDC_VER_ATA7)) { printf("ATAIOCTRIM: %s: not ATA-7\n",device_xname(wd->sc_dev)); return(EINVAL); } if (! (wd->sc_params.support_dsm & ATA_SUPPORT_DSM_TRIM)) { printf("ATAIOCTRIM: %s: has no TRIM support\n",device_xname(wd->sc_dev)); return(EINVAL); } bcopy(addr,&rq[0],8); printf("TRIM %s: arg %02x %02x %02x %02x %02x %02x %02x %02x\n", device_xname(wd->sc_dev), rq[0], rq[1], rq[2], rq[3], rq[4], rq[5], rq[6], rq[7]); bzero(&rq[8],512-8); bzero(&cmd,sizeof(cmd)); // XXX API botch cmd.r_command = ATA_DATA_SET_MANAGEMENT; cmd.r_count = 1; cmd.r_features = ATA_SUPPORT_DSM_TRIM; cmd.r_st_bmask = WDCS_DRDY; cmd.r_st_pmask = WDCS_DRDY; cmd.timeout = 30000; cmd.data = &rq[0]; cmd.bcount = 512; cmd.flags |= AT_WRITE | AT_WAIT; printf("TRIM %s: calling exec\n",device_xname(wd->sc_dev)); rv = wd->atabus->ata_exec_command(wd->drvp,&cmd); printf("TRIM %s: returned %d\n",device_xname(wd->sc_dev),rv); return(0); } break; When I run my userland program, I get [ - root] 3> date; ./trim /dev/rwd1d 4 2; date Wed Dec 7 11:46:43 EST 2022 TRIM wd1: arg 04 00 00 00 00 00 02 00 TRIM wd1: calling exec piixide1:0:1: lost interrupt type: ata tc_bcount: 512 tc_skip: 0 TRIM wd1: returned 1 ATAIOCTRIM workd wd1: wd_flushcache: status=128<TIMEOU> Wed Dec 7 11:47:43 EST 2022 [ - root] 4> 1 is ATACMD_COMPLETE. (The "ATAIOCTRIM workd" message is coming from the userland program.) Then attempting to read the drive times out but recovers: [ - root] 4> dd if=/dev/rwd1d of=/dev/null bs=512 count=64 piixide1:0:1: wait timed out wd1d: device timeout reading fsbn 0 (wd1 bn 0; cn 0 tn 0 sn 0), retrying wd1: soft error (corrected) 64+0 records in 64+0 records out 32768 bytes transferred in 0.008 secs (4096000 bytes/sec) [ - root] 5> Reading the device after that, I find the original contents are still accessible up through (at least) sector 17, so the TRIM did not actually work. wd1 is a Kingston SATA SSD: wd1 at atabus1 drive 1: <KINGSTON SA400S37120G> wd1: drive supports 1-sector PIO transfers, LBA48 addressing wd1: HPA enabled, no protected area wd1: 111 GB, 232581 cyl, 16 head, 63 sec, 512 bytes/sect x 234441648 sectors wd1: 32-bit data port wd1: drive supports PIO mode 4, DMA mode 2, Ultra-DMA mode 6 (Ultra/133) wd1: non-rotational device wd1(piixide1:0:1): using PIO mode 4, Ultra-DMA mode 6 (Ultra/133) (using DMA) /~\ The ASCII Mouse \ / Ribbon Campaign X Against HTML mo...@rodents-montreal.org / \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B