Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'include/llfio/v2.0/detail/impl/windows/file_handle.ipp')
-rw-r--r--include/llfio/v2.0/detail/impl/windows/file_handle.ipp111
1 files changed, 110 insertions, 1 deletions
diff --git a/include/llfio/v2.0/detail/impl/windows/file_handle.ipp b/include/llfio/v2.0/detail/impl/windows/file_handle.ipp
index 610f20b1..5b36810f 100644
--- a/include/llfio/v2.0/detail/impl/windows/file_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/file_handle.ipp
@@ -25,6 +25,11 @@ Distributed under the Boost Software License, Version 1.0.
#include "../../../file_handle.hpp"
#include "import.hpp"
+#include "../../../statfs.hpp"
+
+#include <mutex>
+#include <vector>
+
LLFIO_V2_NAMESPACE_BEGIN
result<file_handle> file_handle::file(const path_handle &base, file_handle::path_view_type path, file_handle::mode _mode, file_handle::creation _creation,
@@ -821,7 +826,7 @@ result<file_handle::extent_pair> file_handle::clone_extents_to(file_handle::exte
}
done = true;
}
- //assert(done);
+ // assert(done);
dest_length = destoffset + extent.length;
truncate_back_on_failure = false;
LLFIO_DEADLINE_TO_TIMEOUT_LOOP(d);
@@ -870,4 +875,108 @@ result<file_handle::extent_type> file_handle::zero(file_handle::extent_pair exte
return success();
}
+
+/******************************************* statfs_t ************************************************/
+
+LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<std::pair<uint32_t, float>> statfs_t::_fill_ios(const handle & /*unused*/, const std::string &mntfromname) noexcept
+{
+ try
+ {
+ alignas(8) wchar_t buffer[32769];
+ // Firstly open a handle to the volume
+ OUTCOME_TRY(auto &&volumeh, file_handle::file({}, mntfromname, handle::mode::none, handle::creation::open_existing, handle::caching::only_metadata));
+ // Now ask the volume what physical disks it spans
+ auto *vde = reinterpret_cast<VOLUME_DISK_EXTENTS *>(buffer);
+ OVERLAPPED ol{};
+ memset(&ol, 0, sizeof(ol));
+ ol.Internal = static_cast<ULONG_PTR>(-1);
+ if(DeviceIoControl(volumeh.native_handle().h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nullptr, 0, vde, sizeof(buffer), nullptr, &ol) == 0)
+ {
+ if(ERROR_IO_PENDING == GetLastError())
+ {
+ NTSTATUS ntstat = ntwait(volumeh.native_handle().h, ol, deadline());
+ if(ntstat != 0)
+ {
+ return ntkernel_error(ntstat);
+ }
+ }
+ if(ERROR_SUCCESS != GetLastError())
+ {
+ return win32_error();
+ }
+ }
+ static struct last_reading_t
+ {
+ struct item
+ {
+ int64_t ReadTime{0}, WriteTime{0}, IdleTime{0};
+ };
+ std::mutex lock;
+ std::vector<item> items;
+ } last_reading;
+
+ uint32_t iosinprogress = 0;
+ float iosbusytime = 0;
+ DWORD disk_extents = vde->NumberOfDiskExtents;
+ for(DWORD disk_extent = 0; disk_extent < disk_extents; disk_extent++)
+ {
+ alignas(8) wchar_t physicaldrivename[32] = L"\\\\.\\PhysicalDrive", *e = physicaldrivename + 17;
+ const auto DiskNumber = vde->Extents[disk_extent].DiskNumber;
+ if(DiskNumber >= 100)
+ {
+ *e++ = '0' + ((DiskNumber / 100) % 10);
+ }
+ if(DiskNumber >= 10)
+ {
+ *e++ = '0' + ((DiskNumber / 10) % 10);
+ }
+ *e++ = '0' + (DiskNumber % 10);
+ *e = 0;
+ OUTCOME_TRY(auto &&diskh, file_handle::file({}, path_view(physicaldrivename, e - physicaldrivename, path_view::zero_terminated), handle::mode::none,
+ handle::creation::open_existing, handle::caching::only_metadata));
+ ol.Internal = static_cast<ULONG_PTR>(-1);
+ auto *dp = reinterpret_cast<DISK_PERFORMANCE *>(buffer);
+ if(DeviceIoControl(diskh.native_handle().h, IOCTL_DISK_PERFORMANCE, nullptr, 0, dp, sizeof(buffer), nullptr, &ol) == 0)
+ {
+ if(ERROR_IO_PENDING == GetLastError())
+ {
+ NTSTATUS ntstat = ntwait(diskh.native_handle().h, ol, deadline());
+ if(ntstat != 0)
+ {
+ return ntkernel_error(ntstat);
+ }
+ }
+ if(ERROR_SUCCESS != GetLastError())
+ {
+ return win32_error();
+ }
+ }
+ //printf("%llu,%llu,%llu\n", dp->ReadTime.QuadPart, dp->WriteTime.QuadPart, dp->IdleTime.QuadPart);
+ iosinprogress += dp->QueueDepth;
+ std::lock_guard<std::mutex> g(last_reading.lock);
+ if(last_reading.items.size() < DiskNumber + 1)
+ {
+ last_reading.items.resize(DiskNumber + 1);
+ }
+ else
+ {
+ uint64_t rd = (uint64_t) dp->ReadTime.QuadPart - (uint64_t) last_reading.items[DiskNumber].ReadTime;
+ uint64_t wd = (uint64_t) dp->WriteTime.QuadPart - (uint64_t) last_reading.items[DiskNumber].WriteTime;
+ uint64_t id = (uint64_t) dp->IdleTime.QuadPart - (uint64_t) last_reading.items[DiskNumber].IdleTime;
+ iosbusytime += 1 - (float) ((double) id / (rd + wd + id));
+ }
+ last_reading.items[DiskNumber].ReadTime = dp->ReadTime.QuadPart;
+ last_reading.items[DiskNumber].WriteTime = dp->WriteTime.QuadPart;
+ last_reading.items[DiskNumber].IdleTime = dp->IdleTime.QuadPart;
+ }
+ iosinprogress /= disk_extents;
+ iosbusytime /= disk_extents;
+ return {iosinprogress, std::min(iosbusytime, 1.0f)};
+ }
+ catch(...)
+ {
+ return error_from_exception();
+ }
+}
+
LLFIO_V2_NAMESPACE_END