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:
authorNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2018-08-24 11:59:28 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2018-08-24 11:59:28 +0300
commit5f82c897584065164c593ea0ca3a602ac651198c (patch)
tree4e1a880af2902e11561aa4608af1d1d1c77f35d6 /include/llfio/v2.0/detail
parent0b0eae81e199476a1f5246c68011bd00d8653363 (diff)
Reworked directory_handle to use same io_request and read() pattern as all the other handles.
Diffstat (limited to 'include/llfio/v2.0/detail')
-rw-r--r--include/llfio/v2.0/detail/impl/posix/directory_handle.ipp112
-rw-r--r--include/llfio/v2.0/detail/impl/storage_profile.ipp6
-rw-r--r--include/llfio/v2.0/detail/impl/windows/directory_handle.ipp50
3 files changed, 90 insertions, 78 deletions
diff --git a/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp b/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
index 247f030b..69bf45cf 100644
--- a/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
@@ -209,16 +209,16 @@ LLFIO_HEADERS_ONLY_MEMFUNC_SPEC result<path_handle> directory_handle::clone_to_p
return ret;
}
-result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_type &&tofill, path_view_type glob, filter /*unused*/, span<char> kernelbuffer) const noexcept
+result<directory_handle::buffers_type> directory_handle::read(io_request<buffers_type> req) const noexcept
{
LLFIO_LOG_FUNCTION_CALL(this);
- if(tofill.empty())
+ if(req.buffers.empty())
{
- return enumerate_info{std::move(tofill), stat_t::want::none, false};
+ return std::move(req.buffers);
}
// Is glob a single entry match? If so, this is really a stat call
- path_view_type::c_str zglob(glob);
- if(!glob.empty() && !glob.contains_glob())
+ path_view_type::c_str zglob(req.glob);
+ if(!req.glob.empty() && !req.glob.contains_glob())
{
struct stat s
{
@@ -227,46 +227,46 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
{
return posix_error();
}
- tofill[0].stat.st_dev = s.st_dev;
- tofill[0].stat.st_ino = s.st_ino;
- tofill[0].stat.st_type = to_st_type(s.st_mode);
- tofill[0].stat.st_perms = s.st_mode & 0xfff;
- tofill[0].stat.st_nlink = s.st_nlink;
- tofill[0].stat.st_uid = s.st_uid;
- tofill[0].stat.st_gid = s.st_gid;
- tofill[0].stat.st_rdev = s.st_rdev;
+ req.buffers[0].stat.st_dev = s.st_dev;
+ req.buffers[0].stat.st_ino = s.st_ino;
+ req.buffers[0].stat.st_type = to_st_type(s.st_mode);
+ req.buffers[0].stat.st_perms = s.st_mode & 0xfff;
+ req.buffers[0].stat.st_nlink = s.st_nlink;
+ req.buffers[0].stat.st_uid = s.st_uid;
+ req.buffers[0].stat.st_gid = s.st_gid;
+ req.buffers[0].stat.st_rdev = s.st_rdev;
#ifdef __ANDROID__
- tofill[0].stat.st_atim = to_timepoint(*((struct timespec *) &s.st_atime));
- tofill[0].stat.st_mtim = to_timepoint(*((struct timespec *) &s.st_mtime));
- tofill[0].stat.st_ctim = to_timepoint(*((struct timespec *) &s.st_ctime));
+ req.buffers[0].stat.st_atim = to_timepoint(*((struct timespec *) &s.st_atime));
+ req.buffers[0].stat.st_mtim = to_timepoint(*((struct timespec *) &s.st_mtime));
+ req.buffers[0].stat.st_ctim = to_timepoint(*((struct timespec *) &s.st_ctime));
#elif defined(__APPLE__)
- tofill[0].stat.st_atim = to_timepoint(s.st_atimespec);
- tofill[0].stat.st_mtim = to_timepoint(s.st_mtimespec);
- tofill[0].stat.st_ctim = to_timepoint(s.st_ctimespec);
+ req.buffers[0].stat.st_atim = to_timepoint(s.st_atimespec);
+ req.buffers[0].stat.st_mtim = to_timepoint(s.st_mtimespec);
+ req.buffers[0].stat.st_ctim = to_timepoint(s.st_ctimespec);
#else // Linux and BSD
- tofill[0].stat.st_atim = to_timepoint(s.st_atim);
- tofill[0].stat.st_mtim = to_timepoint(s.st_mtim);
- tofill[0].stat.st_ctim = to_timepoint(s.st_ctim);
+ req.buffers[0].stat.st_atim = to_timepoint(s.st_atim);
+ req.buffers[0].stat.st_mtim = to_timepoint(s.st_mtim);
+ req.buffers[0].stat.st_ctim = to_timepoint(s.st_ctim);
#endif
- tofill[0].stat.st_size = s.st_size;
- tofill[0].stat.st_allocated = static_cast<handle::extent_type>(s.st_blocks) * 512;
- tofill[0].stat.st_blocks = s.st_blocks;
- tofill[0].stat.st_blksize = s.st_blksize;
+ req.buffers[0].stat.st_size = s.st_size;
+ req.buffers[0].stat.st_allocated = static_cast<handle::extent_type>(s.st_blocks) * 512;
+ req.buffers[0].stat.st_blocks = s.st_blocks;
+ req.buffers[0].stat.st_blksize = s.st_blksize;
#ifdef HAVE_STAT_FLAGS
- tofill[0].stat.st_flags = s.st_flags;
+ req.buffers[0].stat.st_flags = s.st_flags;
#endif
#ifdef HAVE_STAT_GEN
- tofill[0].stat.st_gen = s.st_gen;
+ req.buffers[0].stat.st_gen = s.st_gen;
#endif
#ifdef HAVE_BIRTHTIMESPEC
#if defined(__APPLE__)
- tofill[0].stat.st_birthtim = to_timepoint(s.st_birthtimespec);
+ req.buffers[0].stat.st_birthtim = to_timepoint(s.st_birthtimespec);
#else
- tofill[0].stat.st_birthtim = to_timepoint(s.st_birthtim);
+ req.buffers[0].stat.st_birthtim = to_timepoint(s.st_birthtim);
#endif
#endif
- tofill[0].stat.st_sparse = static_cast<unsigned int>((static_cast<handle::extent_type>(s.st_blocks) * 512) < static_cast<handle::extent_type>(s.st_size));
- tofill._resize(1);
+ req.buffers[0].stat.st_sparse = static_cast<unsigned int>((static_cast<handle::extent_type>(s.st_blocks) * 512) < static_cast<handle::extent_type>(s.st_size));
+ req.buffers._resize(1);
static constexpr stat_t::want default_stat_contents = stat_t::want::dev | stat_t::want::ino | stat_t::want::type | stat_t::want::perms | stat_t::want::nlink | stat_t::want::uid | stat_t::want::gid | stat_t::want::rdev | stat_t::want::atim | stat_t::want::mtim | stat_t::want::ctim | stat_t::want::size |
stat_t::want::allocated | stat_t::want::blocks | stat_t::want::blksize
#ifdef HAVE_STAT_FLAGS
@@ -279,7 +279,9 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
| stat_t::want::birthtim
#endif
| stat_t::want::sparse;
- return enumerate_info{std::move(tofill), default_stat_contents, true};
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = true;
+ return std::move(req.buffers);
}
#ifdef __linux__
// Unlike FreeBSD, Linux doesn't define a getdents() function, so we'll do that here.
@@ -295,17 +297,17 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
return syscall(SYS_getdirentries64, fd, buf, count, &foo);
});
#endif
- if(!tofill._kernel_buffer && kernelbuffer.empty())
+ if(!req.buffers._kernel_buffer && req.kernelbuffer.empty())
{
// Let's assume the average leafname will be 64 characters long.
- size_t toallocate = (sizeof(dirent) + 64) * tofill.size();
+ size_t toallocate = (sizeof(dirent) + 64) * req.buffers.size();
auto *mem = new(std::nothrow) char[toallocate];
if(mem == nullptr)
{
return errc::not_enough_memory;
}
- tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
- tofill._kernel_buffer_size = toallocate;
+ req.buffers._kernel_buffer = std::unique_ptr<char[]>(mem);
+ req.buffers._kernel_buffer_size = toallocate;
}
stat_t::want default_stat_contents = stat_t::want::ino | stat_t::want::type;
dirent *buffer;
@@ -314,8 +316,8 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
bool done = false;
do
{
- buffer = kernelbuffer.empty() ? reinterpret_cast<dirent *>(tofill._kernel_buffer.get()) : reinterpret_cast<dirent *>(kernelbuffer.data());
- bytesavailable = kernelbuffer.empty() ? tofill._kernel_buffer_size : kernelbuffer.size();
+ buffer = req.kernelbuffer.empty() ? reinterpret_cast<dirent *>(req.buffers._kernel_buffer.get()) : reinterpret_cast<dirent *>(req.kernelbuffer.data());
+ bytesavailable = req.kernelbuffer.empty() ? req.buffers._kernel_buffer_size : req.kernelbuffer.size();
// Seek to start
#ifdef __linux__
if(-1 == ::lseek64(_v.fd, 0, SEEK_SET))
@@ -327,17 +329,17 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
return posix_error();
#endif
bytes = getdents(_v.fd, reinterpret_cast<char *>(buffer), bytesavailable);
- if(kernelbuffer.empty() && bytes == -1 && EINVAL == errno)
+ if(req.kernelbuffer.empty() && bytes == -1 && EINVAL == errno)
{
- tofill._kernel_buffer.reset();
- size_t toallocate = tofill._kernel_buffer_size * 2;
+ req.buffers._kernel_buffer.reset();
+ size_t toallocate = req.buffers._kernel_buffer_size * 2;
auto *mem = new(std::nothrow) char[toallocate];
if(mem == nullptr)
{
return errc::not_enough_memory;
}
- tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
- tofill._kernel_buffer_size = toallocate;
+ req.buffers._kernel_buffer = std::unique_ptr<char[]>(mem);
+ req.buffers._kernel_buffer_size = toallocate;
}
else
{
@@ -350,8 +352,10 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
} while(!done);
if(bytes == 0)
{
- tofill._resize(0);
- return enumerate_info{std::move(tofill), default_stat_contents, true};
+ req.buffers._resize(0);
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = true;
+ return std::move(req.buffers);
}
LLFIO_VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(buffer, bytes); // NOLINT
size_t n = 0;
@@ -367,11 +371,11 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
goto cont;
}
}
- if(!glob.empty() && fnmatch(zglob.buffer, dent->d_name, 0) != 0)
+ if(!req.glob.empty() && fnmatch(zglob.buffer, dent->d_name, 0) != 0)
{
goto cont;
}
- directory_entry &item = tofill[n];
+ directory_entry &item = req.buffers[n];
item.leafname = path_view(dent->d_name, length);
item.stat = stat_t(nullptr);
item.stat.st_ino = dent->d_ino;
@@ -410,13 +414,17 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
if((bytes -= dent->d_reclen) <= 0)
{
// Fill is complete
- tofill._resize(n);
- return enumerate_info{std::move(tofill), default_stat_contents, true};
+ req.buffers._resize(n);
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = true;
+ return std::move(req.buffers);
}
- if(n >= tofill.size())
+ if(n >= req.buffers.size())
{
// Fill is incomplete
- return enumerate_info{std::move(tofill), default_stat_contents, false};
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = false;
+ return std::move(req.buffers);
}
}
}
diff --git a/include/llfio/v2.0/detail/impl/storage_profile.ipp b/include/llfio/v2.0/detail/impl/storage_profile.ipp
index be8d4e5c..338dfcbc 100644
--- a/include/llfio/v2.0/detail/impl/storage_profile.ipp
+++ b/include/llfio/v2.0/detail/impl/storage_profile.ipp
@@ -1239,9 +1239,9 @@ namespace storage_profile
std::vector<directory_entry> entries(no);
begin = std::chrono::high_resolution_clock::now();
- directory_handle::enumerate_info ei(dirh.enumerate(entries).value());
- assert(ei.done == true);
- assert(ei.filled.size() == no);
+ directory_handle::buffers_type ei(dirh.read(directory_handle::buffers_type(entries)).value());
+ assert(ei.done() == true);
+ assert(ei.size() == no);
end = std::chrono::high_resolution_clock::now();
s.enumerate = static_cast<unsigned long long>(static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count()) / no);
if(cold_cache)
diff --git a/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp b/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
index 158bbc7f..f8afcfb6 100644
--- a/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
@@ -208,61 +208,61 @@ result<void> directory_handle::unlink(deadline d) noexcept
return h.unlink(d);
}
-result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_type &&tofill, path_view_type glob, filter filtering, span<char> kernelbuffer) const noexcept
+result<directory_handle::buffers_type> directory_handle::read(io_request<buffers_type> req) const noexcept
{
static constexpr stat_t::want default_stat_contents = stat_t::want::ino | stat_t::want::type | stat_t::want::atim | stat_t::want::mtim | stat_t::want::ctim | stat_t::want::size | stat_t::want::allocated | stat_t::want::birthtim | stat_t::want::sparse | stat_t::want::compressed | stat_t::want::reparse_point;
windows_nt_kernel::init();
using namespace windows_nt_kernel;
LLFIO_LOG_FUNCTION_CALL(this);
- if(tofill.empty())
+ if(req.buffers.empty())
{
- return enumerate_info{std::move(tofill), stat_t::want::none, false};
+ return std::move(req.buffers);
}
UNICODE_STRING _glob{};
memset(&_glob, 0, sizeof(_glob));
- path_view_type::c_str zglob(glob, true);
- if(!glob.empty())
+ path_view_type::c_str zglob(req.glob, true);
+ if(!req.glob.empty())
{
_glob.Buffer = const_cast<wchar_t *>(zglob.buffer);
_glob.Length = zglob.length * sizeof(wchar_t);
_glob.MaximumLength = _glob.Length + sizeof(wchar_t);
}
- if(!tofill._kernel_buffer && kernelbuffer.empty())
+ if(!req.buffers._kernel_buffer && req.kernelbuffer.empty())
{
// Let's assume the average leafname will be 64 characters long.
- size_t toallocate = (sizeof(FILE_ID_FULL_DIR_INFORMATION) + 64 * sizeof(wchar_t)) * tofill.size();
+ size_t toallocate = (sizeof(FILE_ID_FULL_DIR_INFORMATION) + 64 * sizeof(wchar_t)) * req.buffers.size();
auto *mem = new(std::nothrow) char[toallocate];
if(mem == nullptr)
{
return errc::not_enough_memory;
}
- tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
- tofill._kernel_buffer_size = toallocate;
+ req.buffers._kernel_buffer = std::unique_ptr<char[]>(mem);
+ req.buffers._kernel_buffer_size = toallocate;
}
FILE_ID_FULL_DIR_INFORMATION *buffer;
ULONG bytes;
bool done = false;
do
{
- buffer = kernelbuffer.empty() ? reinterpret_cast<FILE_ID_FULL_DIR_INFORMATION *>(tofill._kernel_buffer.get()) : reinterpret_cast<FILE_ID_FULL_DIR_INFORMATION *>(kernelbuffer.data());
- bytes = kernelbuffer.empty() ? static_cast<ULONG>(tofill._kernel_buffer_size) : static_cast<ULONG>(kernelbuffer.size());
+ buffer = req.kernelbuffer.empty() ? reinterpret_cast<FILE_ID_FULL_DIR_INFORMATION *>(req.buffers._kernel_buffer.get()) : reinterpret_cast<FILE_ID_FULL_DIR_INFORMATION *>(req.kernelbuffer.data());
+ bytes = req.kernelbuffer.empty() ? static_cast<ULONG>(req.buffers._kernel_buffer_size) : static_cast<ULONG>(req.kernelbuffer.size());
IO_STATUS_BLOCK isb = make_iostatus();
- NTSTATUS ntstat = NtQueryDirectoryFile(_v.h, nullptr, nullptr, nullptr, &isb, buffer, bytes, FileIdFullDirectoryInformation, FALSE, glob.empty() ? nullptr : &_glob, TRUE);
+ NTSTATUS ntstat = NtQueryDirectoryFile(_v.h, nullptr, nullptr, nullptr, &isb, buffer, bytes, FileIdFullDirectoryInformation, FALSE, req.glob.empty() ? nullptr : &_glob, TRUE);
if(STATUS_PENDING == ntstat)
{
ntstat = ntwait(_v.h, isb, deadline());
}
- if(kernelbuffer.empty() && STATUS_BUFFER_OVERFLOW == ntstat)
+ if(req.kernelbuffer.empty() && STATUS_BUFFER_OVERFLOW == ntstat)
{
- tofill._kernel_buffer.reset();
- size_t toallocate = tofill._kernel_buffer_size * 2;
+ req.buffers._kernel_buffer.reset();
+ size_t toallocate = req.buffers._kernel_buffer_size * 2;
auto *mem = new(std::nothrow) char[toallocate];
if(mem == nullptr)
{
return errc::not_enough_memory;
}
- tofill._kernel_buffer = std::unique_ptr<char[]>(mem);
- tofill._kernel_buffer_size = toallocate;
+ req.buffers._kernel_buffer = std::unique_ptr<char[]>(mem);
+ req.buffers._kernel_buffer_size = toallocate;
}
else
{
@@ -289,9 +289,9 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
{
ffdi->FileName[length] = 0;
}
- directory_entry &item = tofill[n];
+ directory_entry &item = req.buffers[n];
item.leafname = path_view(wstring_view(ffdi->FileName, length));
- if(filtering == filter::fastdeleted && item.leafname.is_llfio_deleted())
+ if(req.filtering == filter::fastdeleted && item.leafname.is_llfio_deleted())
{
continue;
}
@@ -311,13 +311,17 @@ result<directory_handle::enumerate_info> directory_handle::enumerate(buffers_typ
if(ffdi->NextEntryOffset == 0u)
{
// Fill is complete
- tofill._resize(n);
- return enumerate_info{std::move(tofill), default_stat_contents, true};
+ req.buffers._resize(n);
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = true;
+ return std::move(req.buffers);
}
- if(n >= tofill.size())
+ if(n >= req.buffers.size())
{
// Fill is incomplete
- return enumerate_info{std::move(tofill), default_stat_contents, false};
+ req.buffers._metadata = default_stat_contents;
+ req.buffers._done = false;
+ return std::move(req.buffers);
}
}
}