tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
ATA TRIM?
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 mouse%rodents-montreal.org@localhost
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
Home |
Main Index |
Thread Index |
Old Index