3

Does OS X sometimes run a TRIM routine with drives that are not explicitly supported?

When an HFS Plus volume is unmounted or ejected, maybe?

Background

Noted recently in Console, whilst repeatedly/aggressively partitioning a simple USB flash drive and erasing its multiple journaled HFS Plus file systems, messages such as this:

2013-12-29 21:56:18.000 kernel[0]: hfs_unmap_free_ext: ignoring trim vol=swivel @ off 4698607616 len 159744 

In System Information, the drive – a Kingston DataTraveler 400 – is not treated as a solid state medium, and there's no 'TRIM Support:' line.

I don't do code, but it seems to me that ignoring trim appears in a part of the code – the hfs_unmap_free_extent routine – that would apply where TRIM is in some way supported.

This leaves me wondering whether – in addition to supposed nanosecond-critical routine(s) that may run whilst a file system is mounted – a lesser-known and relatively crude (less critical) routine can run at other times.


Related

Optimize macbook pro for internal SSD+HDD drives (2011), where the accepted answer drew attention to a July 2011 comment by Hyram in response to an digitaldj.net article by Grant Pannell. Within that comment:

… Apple locked TRIM support for a very good reason — their code works reliably with the SSD’s they’ve chosen to use and no others, because they have programmed in nanosecond-critical timing loops that match perfectly with the access timings of the controllers used in Apple’s SSDs. …

However, a November 2011 digitaldj.net article cast doubt on some of Hyram's statements. In particular:

… There is zero evidence that Apple has specific code to handle their specific SSD hardware for reading and writing. …

Please note, this question is not about third party TRIM Enabler and the like. It's about:

  • what's integral to the operating system

– and I'd like authoritative answers. Evidence-based if possible, although I appreciate that the closed source portions of OS X may make this difficult.


From HFS-related source code for the kernel

/* 
 ;________________________________________________________________________________ 
 ; 
 ; Routine:       hfs_unmap_free_extent 
 ; 
 ; Function:      Make note of a range of allocation blocks that should be 
 ;                unmapped (trimmed).  That is, the given range of blocks no 
 ;                longer have useful content, and the device can unmap the 
 ;                previous contents.  For example, a solid state disk may reuse 
 ;                the underlying storage for other blocks. 
 ; 
 ;                This routine is only supported for journaled volumes.  The extent 
 ;                being freed is passed to the journal code, and the extent will 
 ;                be unmapped after the current transaction is written to disk. 
 ; 
 ; Input Arguments: 
 ;    hfsmp            - The volume containing the allocation blocks. 
 ;    startingBlock    - The first allocation block of the extent being freed. 
 ;    numBlocks        - The number of allocation blocks of the extent being freed. 


;________________________________________________________________________________
 */
static void hfs_unmap_free_extent(struct hfsmount *hfsmp, u_int32_t startingBlock, u_int32_t numBlocks)
{
    u_int64_t offset;
    u_int64_t length;
    u_int64_t device_sz;
    int err = 0;

    if (hfs_kdebug_allocation & HFSDBG_UNMAP_ENABLED)
        KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_FREE | DBG_FUNC_START, startingBlock, numBlocks, 0, 0, 0);

    if (ALLOC_DEBUG) {
        if (hfs_isallocated(hfsmp, startingBlock, numBlocks)) {
            panic("hfs: %p: (%u,%u) unmapping allocated blocks", hfsmp, startingBlock, numBlocks);
        }
    }

    if (hfsmp->jnl != NULL) {
        device_sz = hfsmp->hfs_logical_bytes;
        offset = (u_int64_t) startingBlock * hfsmp->blockSize + (u_int64_t) hfsmp->hfsPlusIOPosOffset;
        length = (u_int64_t) numBlocks * hfsmp->blockSize;

        /* Validate that the trim is in a valid range of bytes */
        if ((offset >= device_sz) || ((offset + length) > device_sz)) {
            printf("hfs_unmap_free_ext: ignoring trim vol=%s @ off %lld len %lld \n", hfsmp->vcbVN, offset, length);
            err = EINVAL;
        }

        if (err == 0) {
            err = journal_trim_add_extent(hfsmp->jnl, offset, length);
            if (err) {
                printf("hfs_unmap_free_extent: error %d from journal_trim_add_extent for vol=%s", err, hfsmp->vcbVN);
            }
        }
    }

    if (hfs_kdebug_allocation & HFSDBG_UNMAP_ENABLED)
        KERNEL_DEBUG_CONSTANT(HFSDBG_UNMAP_FREE | DBG_FUNC_END, err, 0, 0, 0, 0);
}

First appearance in Apple open source: http://www.opensource.apple.com/source/xnu/xnu-2050.9.2/bsd/hfs/hfscommon/Misc/VolumeAllocation.c (Mac OS X 10.8.1)

Most recent appearance: http://www.opensource.apple.com/source/xnu/xnu-2422.1.72/bsd/hfs/hfscommon/Misc/VolumeAllocation.c

Also, from the latter:

/* 
 * Validation Routine to verify that the TRIM list maintained by the journal 
 * is in good shape relative to what we think the bitmap should have.  We should 
 * never encounter allocated blocks in the TRIM list, so if we ever encounter them, 
 * we panic.   
 */ 

/* 
 ;________________________________________________________________________________ 
 ; 
 ; Routine:     hfs_track_unmap_blocks 
 ; 
 ; Function:    Make note of a range of allocation blocks that should be 
 ;              unmapped (trimmed).  That is, the given range of blocks no 
 ;              longer have useful content, and the device can unmap the 
 ;              previous contents.  For example, a solid state disk may reuse 
 ;              the underlying storage for other blocks. 
 ; 
 ;              This routine is only supported for journaled volumes.   
 ;  
 ;              *****NOTE*****:  
 ;              This function should *NOT* be used when the volume is fully  
 ;              mounted.  This function is intended to support a bitmap iteration 
 ;              at mount time to fully inform the SSD driver of the state of all blocks 
 ;              at mount time, and assumes that there is no allocation/deallocation 
 ;              interference during its iteration., 
 ; 
 ; Input Arguments: 
 ;    hfsmp           - The volume containing the allocation blocks. 
 ;    offset          - The first allocation block of the extent being freed. 
 ;    numBlocks       - The number of allocation blocks of the extent being freed. 
 ;    list            - The list of currently tracked trim ranges. 
 ;________________________________________________________________________________ 
 */ 

… and so on.

1
+250

So, by virtue of:

this question is not about third party TRIM Enabler and the like

This cannot be the "right answer" it would seem. But even if thats not what the question is about, that is what the, um, "correct answer" is kind of about? So I'll give it a shot anyway...

The short answer to the title question: in short, no.

There is only one implementation... per supported controller.

hfs_unmap_free_ext doesn't refer to the hfs_unmap_free extent function.

It refers to the kext which does the "hfs_unmap_freeing."

The error,

hfs_unmap_free_ext: ignoring trim can occur for one or both of two reasons:

  • The drive is one that uses a supported controller, but has not been "blessed" with an Apple serial number and firmware. In this case, patching this protection out the kernel extension - what Trim Enabler does - will enable TRIM since the hardware has a driver which supports it.

    (Also, myself, I would consider patching the kernel to be almost the definition of something intergral to the operating system.)

  • It is ignored because although the device advertises that it supports TRIM, there's no TRIM driver in the kernel for that controller, since Apple never shipped a drive based on that controller in the first place. So it just uses generic ATA commands.

(This is probably the case with your drive, due to the "not recognized as an SSD" bit.)


While:

they have programmed in nanosecond-critical timing loops that match perfectly with the access timings of the controllers used in Apple’s SSDs

is a true statement, that's definitely not why Apple locks drives. They do that so you can't get in-warranty support for a third party drive.

Apple doesn't make drives; but if you read up how Tim Cook (while COO) cornered the Asian NAND flash market a few years back - more or less why he's CEO today - you'll understand why flash manufacturers allow Apple to dictate stuff like this.

Other than that, I'm not sure you're going to find much more than that thats "authoritative" I'm afraid. Like you said, most of this stuff is closed source, though you can find traces littered everywhere, with includes like this one. Also, note that TRIM is more of a concept/implementation thing than a standard (at least with anything prior to SATA 3.1).

I can also confidently tell you that TRIM enabled/Apple-logo branded SSDs can only be purchased through GSX (or the grey market). And that Trim Enabler works quite well. I've installed (the more recent versions) in many a production environment.

A couple of links:
http://www.anandtech.com/show/5453/trim-enabler-20-for-os-x-lion-released http://en.wikipedia.org/wiki/Trim_(computing)

  • +1 – the hfs_unmap_free_ext distinction and subsequent bullet points are particularly useful. Thanks. – Graham Perrin Feb 21 '14 at 19:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .