“UNMAP not supported” error on a device that supports UNMAP

hdparmsatascsissdtrim

I was playing with trim/unmap commands on a Samsung SSD (MZ7WD240 model).
To check the unmap support on this device i ran the following command:

hdparm -I /dev/sda | grep TRIM

And as expected the output shows that my device /dev/sda supports trimming:

       *    Data Set Management TRIM supported (limit 8 blocks)
       *    Deterministic read ZEROs after TRIM

So i wanted to manually send some unmap commands using the scsi interface so:

  • I created a sample testfile.
  • I got the beginning Lba of the file:

    hdparm --fibmap /mnt/MyDeviceMountPoint/testFile
    
    /mnt/MyDeviceMountPoint/testFile:
    filesystem blocksize 4096, begins at LBA 0; assuming 512 byte sectors.
    byte_offset  begin_LBA    end_LBA    sectors
              0     274432     274439          8 
    
  • I sent an unmap command using sg_unmap from sg3_utils package to the first block of the file using the scsi interface associated with my device:

    # sg_unmap --lba=274432 --num=1 /dev/sg0
    UNMAP not supported
    
  • Even tried sending the command to the device directly but i always get the UNMAP not supported output:

    # sg_unmap --lba=274432 --num=1 /dev/sda
    UNMAP not supported
    

The device is connected using a SATA controller, I've tried other scsi commands and they work perfectly!
What am i missing?

Best Answer

I've tried other scsi commands and they work perfectly! What am i missing?

Your SSD is SATA so something has to do translation of SCSI commands for it. If you want to send raw commands you should use the set native to the device/controller unless you going to use "ATA Command Pass-Through" - i.e. you have a SCSI device behind a SATA controller but this is not the case here.

Linux's libata knows how to remap some but not all SCSI commands to ATA (see https://github.com/torvalds/linux/blob/e40dc66220b7ff1b816311b135b9298f8ba14ce6/drivers/ata/libata-scsi.c#L4222 ). According to https://events.static.linuxfound.org/sites/events/files/slides/discard_0.pdf the semantics of SCSI's UNMAP don't map well to ATA so it's unlikely that mapping will ever be implemented. However, notice that sending SCSI WRITE SAME with the unmap bit set to libata is translated to ATA TRIM so you could attempt to use that.

TLDR; SCSI UNMAP is not translated by libata. If you want to be protocol agnostic and have Linux do a block layer conversion for you then send a BLKDISCARD (e.g. via the blkdiscard utility).