diff options
author | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2018-08-24 11:59:28 +0300 |
---|---|---|
committer | Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com> | 2018-08-24 11:59:28 +0300 |
commit | 5f82c897584065164c593ea0ca3a602ac651198c (patch) | |
tree | 4e1a880af2902e11561aa4608af1d1d1c77f35d6 /include/llfio/v2.0/detail | |
parent | 0b0eae81e199476a1f5246c68011bd00d8653363 (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')
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); } } } |