Code Monkey home page Code Monkey logo

Comments (14)

tenox7 avatar tenox7 commented on May 27, 2024

Yes so looks like size detection problem. Can you send the whole output? Thanks!

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

This line seems to receive the incorrect information:

    if (!DeviceIoControl(hDisk, IOCTL_SCSI_PASS_THROUGH, Buffer, BufLen, Buffer, BufLen, &BytesRet, NULL))

Then there are Zeroes sitting in the buffer where the variables are read:

    DiskLbaCount = REVERSE_BYTES_LONG64(pReadCapacity->LBA);
    DiskBlockSize = REVERSE_BYTES_LONG(pReadCapacity->BlockLength);

I examined the ScsiPass struct, and it appears that TargetId became 0, SenseInfoLength became 0, and other data changed at all. I also checked within 256 bytes after the Cdb field, no changes there either.

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

Can you tell me more about the environment so I can try to reproduce it? Disk/machine make/model? Windows version? Thanks.

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

Sure...

I reproduced this on two machines.

One is a Dell laptop, with an M.2 SATA hard drive, 1TB from Crucial. Running on Windows 10 x64 ("2004" version). Made sure all erase code was commented out, so I could try debugging the IOCTRL call.

Other is an Acer laptop that I'm trying to return (want to blank out the SSD first), NVMe HFM256GDJTNG-831. Running Windows 10 PE. For some reason, none of the bootable linux USB sticks could see the drive, so I'm using Windows PE instead.

Perhaps it should try to do IOCTL_STORAGE_READ_CAPACITY instead of SCSI_PASSTHROUGH?

Edit: Tried IOCTL_STORAGE_READ_CAPACITY, and it returned 1953525168 sectors, each 512 bytes, for a size of 931.5GB. Don't know why SCSI_PASSTHROUGH is failing.

Edit 2: Looks like the SCSI_PASSTHROUGH trim command just doesn't work. "ERROR: TRIM didn't seem to work". Perhaps Windows 10 is blocking it?

Edit 3: Looks like IOCTL_STORAGE_READ_CAPACITY can verify if SCSI_PASSTHROUGH works or not. I wonder if ATA_PASSTHROUGH or windows nvme pasthrough would work?

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

NVME is not ATA. But it may be worth trying. Perhaps there is another class for NVME all together? Also could try to use IOCTL_STORAGE_READ_CAPACITY and see if it works?

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

I just did a few tests in VirtualBox using normal disk operations (no SCSI bypass stuff here). Actually getting VirtualBox to support the TRIM command took some command line trickery**, but you can do it.

  • Deleting a volume or deleting the partition table will not trigger a trim.
  • Creating a blank NTFS file system using Quick Format will trigger a trim.
  • Deleting a file will trigger a trim.
  • Creating a huge file using SetEndOfFile and SetFileValidData* will expose the prior contents of the disk, and the huge file can be deleted to trigger a trim.
  • Performing FSCTL_FILE_LEVEL_TRIM on a huge file only works on SSDs which ensure that data read back after a Trim is 00 bytes, otherwise the operation will fail.

So it seems the best way to actually trim a disk may be this:

  • Delete all paritions
  • Create a max-size NTFS parition, quick format it
  • Optional: create a huge dummy file using SetEndOfFile and SetFileValidData*, then delete the file
  • Make sure all IO operations have finished, and the disk is synced
  • Delete all partitions

I only tested this on VirtualBox. When VirtualBox sees a trim command, it will shrink the size of the virtual hard disk file, then future reads from those areas of the disk become 00 bytes.

Real SSDs may not necessarily read back 00 bytes after using TRIM, and Windows won't tell you if it actually sent any TRIM commands to the drive successfully.

*To get SetFileValidData to work: (also need to run the program as Admin)

	BOOL okay;
        TOKEN_PRIVILEGES priv = {}, prevPriv = {};
	HANDLE hToken = NULL;
	DWORD returnLength = 0;
	priv.PrivilegeCount = 1;
	priv.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
	okay = LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &priv.Privileges->Luid);
	okay = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
	prevPriv = priv;
	okay = AdjustTokenPrivileges(hToken, false, &priv, sizeof(prevPriv), &prevPriv, &returnLength);

**To get VirtualBox to support the TRIM command:

  • Create your virtual Hard Drive, make sure it is set for Dynamically Allocated size.
  • Detach the virtual hard drive
  • Go to File > Virtual Media Manager
  • Click on the disk
  • Go to Information tab, copy the UUID to the clipboard
  • Go to a command prompt, change directory to "C:\Program Files\Oracle\VirtualBox"
  • Run VBoxManage storageattach "Name of VM HERE" --storagectl "SATA" --port 3 --type hdd --medium {UUID HERE} --discard on

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

VirtualBox is not really supported here because of unknown SCSI controller type. I also don't want to create/delete any files, as this would be filesystem based trim, where I want a real, SCSI controller UNMAP, hence SCSI passthrough stuff. To me the real issue is zero LBA count, which will need to be fixed.

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

Okay, to fix the zero LBA count thing, just use IOCTL_STORAGE_READ_CAPACITY, and compare against the current passthrough code. If they disagree, the passthrough doesn't work.

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

Do you want to send a PR?

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

Looks like simply checking if it got zeroes and erroring out at that point would be sufficient.

    if (DiskLbaCount == 0 && DiskBlockSize == 0)
    {
        error(1, L"Error: SCSI Passthrough is not supported on this drive.");
    }

Here is the code that uses IOCTL_DISK_GET_LENGTH_INFO instead of SCSI passthrough to get the size. I don't really see a point to including it though, because if scsi passthrough fails on something like getting the drive size, it probably won't succeed on a TRIM command either.

    STORAGE_READ_CAPACITY capacity;
    ZeroMemory(&capacity, sizeof(capacity));

    if (!DeviceIoControl(
        (HANDLE)hDisk,             // handle to device
        IOCTL_STORAGE_READ_CAPACITY,  // dwIoControlCode
        NULL,                         // lpInBuffer
        0,                            // nInBufferSize
        (LPVOID)&capacity,         // output buffer
        (DWORD)sizeof(capacity),       // size of output buffer
        (LPDWORD)&BytesRet,    // number of bytes returned
        NULL  // OVERLAPPED structure 
    ))
    {
        error(1, L"Error on DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO");
    }

    DiskLbaCount = (ULONG64)capacity.NumberOfBlocks.QuadPart;
    DiskBlockSize = (ULONG)capacity.BlockLength;

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

OK but wait have you tried if passthrough for trim works? Perhaps it's just size info that doesn't work. Have you tried to use IOCTL_STORAGE_READ_CAPACITY and feed it to the UNMAP passthrough?

from disktrim.

Dwedit avatar Dwedit commented on May 27, 2024

When I tried it with a correct LBA count and Block size, none of the DeviceIoControl calls returned false, but when it checked the test pattern, it displayed "TRIM didn't seem to work".

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

I think there may be some problem with the M.2 SATA bus. Perhaps it doesn't support SCSI passthrough? Maybe it comes up as some legacy ATA bus in Windows. Can you see how is it connected in Windows? How about wmic diskdrive for starters. Maybe we could also debug it with busTRACE.

from disktrim.

tenox7 avatar tenox7 commented on May 27, 2024

Can you download busTRACE capture client from this page: http://www.bustrace.com/downloads/free_utilities.php then do capture an unmodified vanilla version of disktrim and send me the capture file? Thanks.

from disktrim.

Related Issues (2)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.