user152949
user152949

Reputation:

DeviceIoControl returning unexpected physical sector size

I use DeviceIoControl to return the size of a physical disk sector. It has always returned 512 bytes, until lately where it started returing 4096 bytes. Inspecting the resulting STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR I see that the logical and physical byte sizes has switched places - should not the logial byte size of a disk sector always be greater or equal to the physical sector size?

#include <Windows.h>
#include <iostream>
#include <Windows.h>

#pragma comment(lib, "Kernel32.lib")

int main()
{
    HANDLE hDevice;

    char cDisk = 'c';   // Get metadata about the C:\ disk

    // Build the logical drive path and get the drive device handle
    std::wstring logicalDrive = L"\\\\.\\";
    wchar_t drive[3];
    drive[0] = cDisk;
    drive[1] = L':';
    drive[2] = L'\0';
    logicalDrive.append(drive);

    hDevice = CreateFile(
        logicalDrive.c_str(),
        0, 
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);

    if (hDevice == INVALID_HANDLE_VALUE)
    {
        std::cerr << "Error\n";
        return -1;
    }   

    // Now that we have the device handle for the disk, let us get disk's metadata
    DWORD outsize;
    STORAGE_PROPERTY_QUERY storageQuery;
    memset(&storageQuery, 0, sizeof(STORAGE_PROPERTY_QUERY));
    storageQuery.PropertyId = StorageAccessAlignmentProperty;
    storageQuery.QueryType  = PropertyStandardQuery;

    STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR diskAlignment = {0};
    memset(&diskAlignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));

    if (!DeviceIoControl(hDevice, 
        IOCTL_STORAGE_QUERY_PROPERTY, 
        &storageQuery, 
        sizeof(STORAGE_PROPERTY_QUERY), 
        &diskAlignment,
        sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), 
        &outsize,
        NULL)
        )
    {
        std::cerr << "Error\n";
        return -1;
    }

    std::cout << "Physical sector size: " diskAlignment.BytesPerPhysicalSector << std::endl;
    std::cout << "Logical sector size: " diskAlignment.BytesPerLogicalSector << std::endl;

    return 0;
}

Result from running the above code is:

Physical sector size: 4096
Logical sector size: 512

Running fsutil gives the same unexpected result.

C:\WINDOWS\system32>fsutil fsinfo ntfsinfo c:
NTFS Version   :                  3.1
LFS Version    :                  2.0
Number Sectors :                  0x000000001741afff
Total Clusters :                  0x0000000002e835ff
Free Clusters  :                  0x0000000000999d28
Total Reserved :                  0x0000000000003260
Bytes Per Sector  :               512
Bytes Per Physical Sector :       4096
Bytes Per Cluster :               4096
Bytes Per FileRecord Segment    : 1024
Clusters Per FileRecord Segment : 0

What am I doing wrong?

Upvotes: 4

Views: 2257

Answers (2)

Asad Altimeemy
Asad Altimeemy

Reputation: 1

The 4096 byte is 8 sectors and called cluster. When you save a file, you save into one or more cluster. If the file has a size greater than 512 byte it will be saved into a cluster. The empty sectors are called slack. Some malware writes themselves into empty sectors to hide in plain sight. FAT file system uses 16 or 32 sectors for one cluster.

Upvotes: -1

M. Jahedbozorgan
M. Jahedbozorgan

Reputation: 7054

Nothing wrong here. From 'File Buffering' article of MSDN:

Application developers should take note of new types of storage devices being introduced into the market with a physical media sector size of 4,096 bytes. The industry name for these devices is "Advanced Format". As there may be compatibility issues with directly introducing 4,096 bytes as the unit of addressing for the media, a temporary compatibility solution is to introduce devices that emulate a regular 512-byte sector storage device but make available information about the true sector size through standard ATA and SCSI commands. As a result of this emulation, there are in essence two sector sizes that developers will need to understand:

  • Logical Sector: The unit that is used for logical block addressing for the media. We can also think of it as the smallest unit of write
    that the storage can accept. This is the "emulation".
  • Physical Sector: The unit for which read and write operations to the device are completed in a single operation. This is the unit of atomic write, and what unbuffered I/O will need to be aligned to in
    order to have optimal performance and reliability characteristics.

Upvotes: 2

Related Questions