KDiskMark icon indicating copy to clipboard operation
KDiskMark copied to clipboard

[REQUEST] fio 3.31 Windows

Open dsm opened this issue 2 years ago • 2 comments

Beginning with fio 3.31 Windows installers are available on GitHub at https://github.com/axboe/fio/releases can we support Windows OS ?

dsm avatar Aug 24 '22 13:08 dsm

any progress ? latest appimage with fio 3.32 and i think fio support windows and why we can't support ?

dsm avatar Oct 11 '22 12:10 dsm

To support windows, we need:

  • set windowsaio as default ioengine for windows, libaio for linux, (posixaio for android)
  • path helper function, if any, should accept '/', '\' or even mixed path

List storage devices

Logical Devices

GetLogicalDrives returns a bit mask presents drive letters in use as bit_1_pos + 'A'

from win32api import GetLogicalDrives

# for example, `0b_1100` means there are C:/ and D:/.
def logical_drives():
   bit_mask = GetLogicalDrives()
   for offset in range(26):
      alphabet = chr(ord('A') + offset)
      if (1 << offset) & bit_mask:
          yield alphabet

Volumes

With Powershell[^0]:

[^0]: https://winreg-kb.readthedocs.io/en/latest/sources/system-keys/Mounted-devices.html#notes)

Get-Volume

With mountvol.exe

mountvol /L

With FindFirstVolumeW and FindNextVolumeW

from winsys._kernel32 import FindFirstVolume, FindNextVolume
handle, first = FindFirstVolume()
volumes = [first]

while (volume := FindNextVolume(handle)) and isinstance(volume, str):
    volumes.append(volume)

print(volumes)

Get device model

drive letter -> Model

With Powershell^1

Get-Disk (Get-Partition -DriveLetter 'C').DiskNumber | select -Prop FriendlyName

drive letter or any volume path -> DeviceId

With Powershell^1 (drive letters only)

(Get-Partition -DriveLetter 'C').DiskNumber

With IOCTL_STORAGE_GET_DEVICE_NUMBER

#include <stdio.h>
#include <Windows.h>
#include <fileapi.h>
#include <winioctl.h>

int get_disk_number_by_drive_letter(char letter) {
    char logical_drive_path[7];
    sprintf(logical_drive_path, "\\\\.\\%c:", letter);
    // '\\?\Volume{<GUID>}' is also applicable to this
    HANDLE hDevice = CreateFileA(logical_drive_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "Failed to open device. Error code: %lu\n", GetLastError());
        return -1;
    }

    STORAGE_DEVICE_NUMBER device_number;
    DWORD bytes_returned;
    if (!DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &device_number, sizeof(device_number), &bytes_returned, NULL)) {
        fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER failed. Error code: %lu\n", GetLastError());
        CloseHandle(hDevice);
        return -1;
    }

    CloseHandle(hDevice);
    return device_number.DeviceNumber;
}

DeviceId -> Model

With Powershell

Get-Disk | select -Prop Number,FriendlyName

With wmic

wmic diskdrive get index,model

With wmi

from win32com.client import GetObject

def get_diskdrive_info():
    wmi = GetObject(r"winmgmts:\\.\root\cimv2")
    disks = wmi.ExecQuery("SELECT * FROM Win32_DiskDrive")

    disk_info = {disk.Index: disk.Model for disk in disks}
    return disk_info

disk_info = sorted(get_diskdrive_info().items())

for index, model in disk_info:
    print(f"{index}: {model}")

Anyway, the most accurate way is to call smartctl ... X:

Additional (maybe) useful syscalls

QueryDosDeviceW should be the proper way to match logical device with \Device\HarddiskVolumeX.

GetDiskFreeSpaceExA gives free space avaliable for the caller user, total disk size, and total free space.

from win32file import GetDiskFreeSpaceEx
list(map(lambda size: size / (1024**3), GetDiskFreeSpaceEx("C:")))
# [58.516212463378906, 117.97948837280273, 58.516212463378906]

Thanks [^2] for cleaning up my confusion to Win32 Paths. [^2]: https://chrisdenton.github.io/omnipath/Overview.html

MeowKatee avatar Feb 04 '24 14:02 MeowKatee