CFT: TRIM Consolodation on UFS/FFS filesystems
Mark Millard
marklmi at yahoo.com
Sun Sep 9 21:00:08 UTC 2018
[I looked up the e.MMC 4.41 information: TRIM was optional back
then. TRIM and DISCARD are Mandatory in e.MMC 4.51 . Also It
looks to me like microsd{hc,xc} cards do not use
EXT_CSD_INAND_CMD38_TRIM in FreeBSD, instead using
EXT_CSD_INAND_CMD38_ERASE .]
On 2018-Sep-8, at 2:32 AM, Mark Millard <marklmi at yahoo.com> wrote:
> On 2018-Sep-8, at 1:36 AM, Mark Millard <marklmi at yahoo.com> wrote:
>
>> Just an FYI.
>>
>> I figured out a hack that allows the e.MMC on a microsd card
>> adapter to be used to boot and operate the Pine64+ 2GB, in
>> DDR52 mode at that. (And so shows what was missing in the
>> FreeBSD operation even if the code change is not the
>> proper form of an official fix.)
>>
>> But in the process I discovered that FreeBSD is using
>> (for e.MMC in this tested context):
>>
>> mmc0: REQUEST: CMD38 arg 0x1 flags 0x1d
>>
>> That "0x1" means: TRIM that forces reads of zeros: the true
>> Data Removal command for mmc protocol, a form of erase. 0x3
>> would be DISCARD, the "performance command" that does not
>> guarantee what would be read afterwards: no erase required.
>>
>> TRIM is older (added in e/MCC 4.4). DISCARD is newer (added
>> in e.MMC 4.5). Each is mandatory when the version has the
>> function at all.
I looked up the e.MMC 4.41 information: TRIM was optional back
then. TRIM and DISCARD are Mandatory in e.MMC 4.51 .
Sorry for the error.
>> Does FreeBSD have a policy of preferring erasure when
>> there is also the option to not require it?
>
>
> I looked up published SD card material and that command
> set encodes differently for the argument:
>
> 0x1 is DISCARD (also not requiring an erase)
> 0x2 is FULE when start LBA=LBA0 and end LBA=MaxLBA.
> Otherwise it is ERASE.
> (FreeBSD's mmcsd_delete uses 0x0 for ERASE selection.)
>
> (I ignore handling violations of start LBA <= end LBA <= Max LBA
> or out of order command sequences. FULE: Full User Area Logical
> Erase.)
>
> It looks like FreeBSD uses mmcsd_delete for both SD and e.MMC
> and it is coded for SD to be more optimal (DISCARD), not
> differentiating e.MMC from SD for argument values to use.
>
> In e.MMC 4.5+ 0x2 is a "discard enable" bit in the argument,
> and never a FULE or other such.
>
> In e.MMC the 0x0 case for CMD38's argument is for performing
> an erase on erase group(s) instead of sector(s).
>
> (I'm not describing Secure Request or Force Garbage Collect
> being 0x1 for e.MMC: apparently unused by mmcsd_delete .)
[I'll note that on the e.MMC fsck_ffs -E with around 60 GiBytes
of free space, gstat -pd shows it taking a long time doing
deletes for the e.MMC that I have.]
It looks to me like microsd{hc,xc} cards and SD cards in
general do not use EXT_CSD_INAND_CMD38_TRIM. I say that
because . . .
Earlier I looked at what the CMD38 command encoding covered.
But that need not mean that TRIM is always used. So I looked
into that as well.
Example code uses MMCSD_USE_TRIM is:
use_trim = sc->flags & MMCSD_USE_TRIM;
. . .
if ((sc->flags & MMCSD_INAND_CMD38) != 0) {
err = mmc_switch(mmcbus, dev, sc->rca, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_INAND_CMD38, use_trim == true ?
EXT_CSD_INAND_CMD38_TRIM : EXT_CSD_INAND_CMD38_ERASE,
sc->cmd6_time, true);
. . .
But the sc->flags bit involved is based on the mmcsd_attach's:
static int
mmcsd_attach(device_t dev)
{
device_t mmcbus;
struct mmcsd_softc *sc;
const uint8_t *ext_csd;
off_t erase_size, sector_size, size, wp_size;
uintmax_t bytes;
int err, i;
uint32_t quirks;
uint8_t rev;
bool comp, ro;
char unit[2];
sc = device_get_softc(dev);
sc->dev = dev;
sc->mmcbus = mmcbus = device_get_parent(dev);
sc->mode = mmc_get_card_type(dev);
/*
* Note that in principle with an SDHCI-like re-tuning implementation,
* the maximum data size can change at runtime due to a device removal/
* insertion that results in switches to/from a transfer mode involving
* re-tuning, iff there are multiple devices on a given bus. Until now
* mmc(4) lacks support for rescanning already attached buses, however,
* and sdhci(4) to date has no support for shared buses in the first
* place either.
*/
sc->max_data = mmc_get_max_data(dev);
sc->high_cap = mmc_get_high_cap(dev);
sc->rca = mmc_get_rca(dev);
sc->cmd6_time = mmc_get_cmd6_timeout(dev);
quirks = mmc_get_quirks(dev);
/* Only MMC >= 4.x devices support EXT_CSD. */
if (mmc_get_spec_vers(dev) >= 4) {
MMCBUS_ACQUIRE_BUS(mmcbus, dev);
err = mmc_send_ext_csd(mmcbus, dev, sc->ext_csd);
MMCBUS_RELEASE_BUS(mmcbus, dev);
if (err != MMC_ERR_NONE) {
device_printf(dev, "Error reading EXT_CSD %s\n",
mmcsd_errmsg(err));
return (ENXIO);
}
}
ext_csd = sc->ext_csd;
if ((quirks & MMC_QUIRK_INAND_CMD38) != 0) {
if (mmc_get_spec_vers(dev) < 4) {
device_printf(dev,
"MMC_QUIRK_INAND_CMD38 set but no EXT_CSD\n");
return (EINVAL);
}
sc->flags |= MMCSD_INAND_CMD38;
}
/*
* EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN denotes support for both
* insecure and secure TRIM.
*/
if ((ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT] &
EXT_CSD_SEC_FEATURE_SUPPORT_GB_CL_EN) != 0 &&
(quirks & MMC_QUIRK_BROKEN_TRIM) == 0) {
if (bootverbose)
device_printf(dev, "taking advantage of TRIM\n");
sc->flags |= MMCSD_USE_TRIM;
sc->erase_sector = 1;
} else
sc->erase_sector = mmc_get_erase_sector(dev);
. . .
microsd{hc,xc} cards do not have EXT_CSD and so would not appear
to ever assign sc->flags |= MMCSD_USE_TRIM . [mmc_send_ext_csd
establishes a zero'd area when the operation fails. For SD cards
CMD8 is only valid for the Idle state, which is not the
context here from what I can tell.]
So I get that EXT_CSD_INAND_CMD38_TRIM is only used for
e.MMC, not (micro)SD{hc,xc} cards.
This means my earlier microsdxc card testing was not testing what
I thought it was: instead testing EXT_CSD_INAND_CMD38_ERASE use.
===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)
More information about the freebsd-fs
mailing list