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>2016-08-18 22:41:16 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2016-08-18 22:41:16 +0300
commit4bc8c759d75336b2f59b5a1f30f9dc6871fd731d (patch)
tree9c725050188af86cf187d940ba7bc636a5de51ec
parent62a9655508ebd66fbc47aabfbc708837dfe685dd (diff)
Added a proper unit test for the new section_handle, and in so doing found and fixed many bugs.
-rw-r--r--CMakeLists.txt4
m---------include/boost/afio/boost-lite0
m---------include/boost/afio/outcome0
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/handle.ipp1
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/import.hpp4
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp30
-rw-r--r--include/boost/afio/v2.0/handle.hpp7
-rw-r--r--include/boost/afio/v2.0/map_handle.hpp7
m---------test/kerneltest0
-rw-r--r--test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp2
-rw-r--r--test/tests/section_handle_create_close/runner.cpp51
11 files changed, 80 insertions, 26 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78c5552c..947d21a7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,7 +49,7 @@ all_compile_features(PUBLIC
cxx_noexcept
cxx_constexpr
cxx_thread_local
- #cxx_init_captures ## Not supported yet by cmake 3.6
+ cxx_lambda_init_captures
cxx_attributes
cxx_generic_lambdas
)
@@ -59,7 +59,7 @@ if(NOT MSVC OR CMAKE_VERSION VERSION_GREATER 3.59)
)
endif()
# Set the library dependencies this library has
-all_link_libraries(PUBLIC boost-lite_hl outcome_hl)
+all_link_libraries(PUBLIC boost-lite_hl outcome_hl kerneltest_hl)
# Set any macros this library requires
if(WIN32)
all_compile_definitions(PRIVATE _WIN32_WINNT=0x600) ## Target WinVista
diff --git a/include/boost/afio/boost-lite b/include/boost/afio/boost-lite
-Subproject 1fb23154efc58f747ff4778801ee4cdbc7c74ca
+Subproject 9c5efbb8ae4a2c6cf9b0a69b6247d24807b343a
diff --git a/include/boost/afio/outcome b/include/boost/afio/outcome
-Subproject 058f256343adf44bbfd924f14c7c8bf7a779f8c
+Subproject 876acd5d1d4daf1342ab93c10f56f08de47c653
diff --git a/include/boost/afio/v2.0/detail/impl/windows/handle.ipp b/include/boost/afio/v2.0/detail/impl/windows/handle.ipp
index 2603604b..3c80a3fa 100644
--- a/include/boost/afio/v2.0/detail/impl/windows/handle.ipp
+++ b/include/boost/afio/v2.0/detail/impl/windows/handle.ipp
@@ -53,6 +53,7 @@ handle::~handle()
if(ret.has_error())
{
BOOST_AFIO_LOG_FATAL(_v.h, "handle::~handle() close failed");
+ abort();
}
}
}
diff --git a/include/boost/afio/v2.0/detail/impl/windows/import.hpp b/include/boost/afio/v2.0/detail/impl/windows/import.hpp
index 9f8fa7a0..245eead3 100644
--- a/include/boost/afio/v2.0/detail/impl/windows/import.hpp
+++ b/include/boost/afio/v2.0/detail/impl/windows/import.hpp
@@ -579,9 +579,9 @@ namespace windows_nt_kernel
if(!AdjustTokenPrivileges)
if(!(AdjustTokenPrivileges = (AdjustTokenPrivileges_t) GetProcAddress(advapi32, "AdjustTokenPrivileges")))
abort();
+ // Only provided on Windows 8 and above
if(!PrefetchVirtualMemory_)
- if(!(PrefetchVirtualMemory_ = (PrefetchVirtualMemory_t) GetProcAddress(kernel32, "PrefetchVirtualMemory ")))
- abort();
+ PrefetchVirtualMemory_ = (PrefetchVirtualMemory_t) GetProcAddress(kernel32, "PrefetchVirtualMemory");
#ifdef BOOST_AFIO_OP_STACKBACKTRACEDEPTH
if(dbghelp)
{
diff --git a/include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp b/include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp
index 05901baa..d4588bd8 100644
--- a/include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp
+++ b/include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp
@@ -46,6 +46,9 @@ result<section_handle> section_handle::section(file_handle &backing, extent_type
maximum_size = length;
}
maximum_size = utils::round_up_to_page_size(maximum_size);
+ // On Windows, no protection means reserve don't commit
+ if(!_flag)
+ _flag = flag::nocommit;
result<section_handle> ret(section_handle(native_handle_type(), backing.is_valid() ? &backing : nullptr, maximum_size, _flag));
native_handle_type &nativeh = ret.get()._v;
ACCESS_MASK access = SECTION_QUERY;
@@ -55,24 +58,34 @@ result<section_handle> section_handle::section(file_handle &backing, extent_type
if(_flag & flag::read)
{
access |= SECTION_MAP_READ;
- prot = PAGE_READONLY;
nativeh.behaviour |= native_handle_type::disposition::readable;
}
if(_flag & flag::write)
{
access |= SECTION_MAP_WRITE;
- prot = PAGE_READWRITE;
nativeh.behaviour |= native_handle_type::disposition::writable;
}
if(_flag & flag::execute)
{
access |= SECTION_MAP_EXECUTE;
- prot = PAGE_EXECUTE;
}
- if(_flag & flag::cow)
+ if(!!(_flag & flag::cow) && !!(_flag & flag::execute))
+ prot = PAGE_EXECUTE_WRITECOPY;
+ else if(_flag & flag::execute)
+ prot = PAGE_EXECUTE;
+ else if(_flag & flag::cow)
prot = PAGE_WRITECOPY;
+ else if(_flag & flag::write)
+ prot = PAGE_READWRITE;
+ else if(_flag & flag::read)
+ prot = PAGE_READONLY;
+ else
+ prot = PAGE_NOACCESS;
if(_flag & flag::nocommit)
+ {
attribs = SEC_RESERVE;
+ prot = PAGE_READONLY; // Windows doesn't permit PAGE_NOACCESS for reservations
+ }
else
attribs = SEC_COMMIT;
if(_flag & flag::executable)
@@ -86,9 +99,11 @@ result<section_handle> section_handle::section(file_handle &backing, extent_type
// InitializeObjectAttributes(&ObjectAttributes, &NULL, 0, NULL, NULL);
LARGE_INTEGER _maximum_size;
_maximum_size.QuadPart = maximum_size;
- NTSTATUS ntstat = NtCreateSection(&nativeh.h, access, NULL, &_maximum_size, prot, attribs, backing.is_valid() ? backing.native_handle().h : NULL);
+ HANDLE h;
+ NTSTATUS ntstat = NtCreateSection(&h, access, NULL, &_maximum_size, prot, attribs, backing.is_valid() ? backing.native_handle().h : NULL);
if(STATUS_SUCCESS != ntstat)
return make_errored_result_nt<section_handle>(ntstat);
+ nativeh.h = h;
return ret;
}
@@ -116,6 +131,7 @@ map_handle::~map_handle()
if(ret.has_error())
{
BOOST_AFIO_LOG_FATAL(_v.h, "map_handle::~map_handle() close failed");
+ abort();
}
}
}
@@ -214,7 +230,7 @@ result<map_handle::buffer_type> map_handle::commit(buffer_type region, section_h
DWORD prot = 0;
if(_flag == section_handle::flag::none)
{
- BOOST_OUTCOME_FILTER_ERROR(_region, dontneed(region));
+ BOOST_OUTCOME_FILTER_ERROR(_region, do_not_store(region));
if(!VirtualProtect(_region.first, _region.second, PAGE_NOACCESS, NULL))
return make_errored_result<buffer_type>(GetLastError());
return _region;
@@ -264,7 +280,7 @@ result<span<map_handle::buffer_type>> map_handle::prefetch(span<buffer_type> reg
return regions;
}
-result<map_handle::buffer_type> map_handle::dontneed(buffer_type region) noexcept
+result<map_handle::buffer_type> map_handle::do_not_store(buffer_type region) noexcept
{
region = utils::round_to_page_size(region);
if(!VirtualAlloc(region.first, region.second, MEM_RESET, 0))
diff --git a/include/boost/afio/v2.0/handle.hpp b/include/boost/afio/v2.0/handle.hpp
index 65bb9683..ed522d7f 100644
--- a/include/boost/afio/v2.0/handle.hpp
+++ b/include/boost/afio/v2.0/handle.hpp
@@ -362,8 +362,11 @@ public:
public:
//! Default constructor
constexpr io_handle() = default;
- //! Same constructors as handle
- using handle::handle;
+ //! Construct a handle from a supplied native handle
+ BOOST_CXX14_CONSTEXPR io_handle(native_handle_type h, caching caching = caching::none, flag flags = flag::none)
+ : handle(h, caching, flags)
+ {
+ }
//! Explicit conversion from handle permitted
explicit io_handle(handle &&o) noexcept : handle(std::move(o)) {}
using handle::really_copy;
diff --git a/include/boost/afio/v2.0/map_handle.hpp b/include/boost/afio/v2.0/map_handle.hpp
index 042f0219..19d24293 100644
--- a/include/boost/afio/v2.0/map_handle.hpp
+++ b/include/boost/afio/v2.0/map_handle.hpp
@@ -86,7 +86,7 @@ public:
}
//! Construct a section handle using the given native handle type for the section and the given i/o handle for the backing storage
explicit section_handle(native_handle_type sectionh, io_handle *backing, extent_type maximum_size, flag __flag)
- : handle(sectionh)
+ : handle(sectionh, handle::caching::all)
, _backing(backing)
, _length(maximum_size)
, _flag(__flag)
@@ -175,6 +175,9 @@ inline std::ostream &operator<<(std::ostream &s, const section_handle::flag &v)
\note The native handle returned by this map handle is always that of the backing storage, but closing this handle
does not close that of the backing storage, nor does releasing this handle release that of the backing storage.
Locking byte ranges of this handle is therefore equal to locking byte ranges in the original backing storage.
+
+\todo MADV_NOSYNC on FreeBSD needs to applied when the file is temporary
+\todo MADV_FREE on FreeBSD seems to do what MADV_DONTNEED does on Linux, investigate.
*/
class BOOST_AFIO_DECL map_handle : public io_handle
{
@@ -280,7 +283,7 @@ public:
//! Ask the system to unset the dirty flag for the memory represented by the buffer. This will prevent any changes not yet sent to the backing storage from being sent in the future, also if the system kicks out this page and reloads it you may see some edition of the underlying storage instead of what was here. addr
//! and length should be page aligned (see utils::page_sizes()), if not the returned buffer is the region actually undirtied.
- static result<buffer_type> dontneed(buffer_type region) noexcept;
+ static result<buffer_type> do_not_store(buffer_type region) noexcept;
/*! \brief Read data from the mapped view.
diff --git a/test/kerneltest b/test/kerneltest
-Subproject a96c2e797c4cf2d4e292c46d2c2d3d37df9cb6e
+Subproject d07a2d2198edf35d2f16b9d9894166e19004ddd
diff --git a/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp b/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
index 3bf8c91b..50b4d70d 100644
--- a/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
+++ b/test/tests/section_handle_create_close/kernel_section_handle.cpp.hpp
@@ -10,8 +10,6 @@ namespace section_handle_create_close
BOOST_AFIO_TEST_KERNEL_DECL boost::outcome::result<boost::afio::section_handle> test_kernel_section_handle(boost::afio::file_handle &backing, boost::afio::section_handle::extent_type maximum_size, boost::afio::section_handle::flag m)
{
auto h = boost::afio::section_handle::section(backing, maximum_size, m);
- if(h)
- h.get().close();
return h;
}
}
diff --git a/test/tests/section_handle_create_close/runner.cpp b/test/tests/section_handle_create_close/runner.cpp
index dd9bfb33..94f047c6 100644
--- a/test/tests/section_handle_create_close/runner.cpp
+++ b/test/tests/section_handle_create_close/runner.cpp
@@ -12,25 +12,58 @@ template <class U> inline void section_handle_create_close_(U &&f)
using namespace BOOST_AFIO_V2_NAMESPACE;
// Create a temporary file and put some text into it
- auto temph = file_handle::file("tempfile", file_handle::mode::write, file_handle::creation::if_needed).get();
- temph.write(0, "niall is not here", 17).get();
+ file_handle temph;
auto boundf = [&](auto... pars) { return f(temph, pars...); };
// clang-format off
- static const auto permuter(mt_permute_parameters<
+ static const auto permuter(st_permute_parameters<
result<void>,
parameters<
typename section_handle::extent_type,
typename section_handle::flag
>,
- precondition::filesystem_setup_parameters
+ precondition::filesystem_setup_parameters,
+ postcondition::custom_parameters<bool>
>(
{
- // Does the mode parameter have the expected side effects?
- { make_ready_result<void>(), { 1, section_handle::flag::read }, { "_" } },
- },
- precondition::filesystem_setup()
- ));
+ { make_ready_result<void>(),{ 1, section_handle::flag::none },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::read },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::cow },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::execute },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write|section_handle::flag::nocommit },{ "_" },{ false } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write|section_handle::flag::prefault },{ "_" },{ false } },
+ //{ make_ready_result<void>(),{ 1, section_handle::flag::write|section_handle::flag::executable },{ "_" },{ false } },
+
+ { make_ready_result<void>(),{ 1, section_handle::flag::none },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::read },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::cow },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::execute },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write | section_handle::flag::nocommit },{ "_" },{ true } },
+ { make_ready_result<void>(),{ 1, section_handle::flag::write | section_handle::flag::prefault },{ "_" },{ true } },
+ //{ make_ready_result<void>(),{ 1, section_handle::flag::write|section_handle::flag::executable },{ "_" },{ true } },
+ },
+ precondition::filesystem_setup(),
+ postcondition::custom(
+ [&](auto *, auto &testreturn, size_t, int use_file_backing) {
+ if (use_file_backing)
+ {
+ temph = file_handle::file("tempfile", file_handle::mode::write, file_handle::creation::if_needed).get();
+ temph.write(0, "niall is not here", 17).get();
+ }
+ else
+ temph = file_handle();
+ return &testreturn;
+ },
+ [&](auto *testreturn) {
+ // Need to close the section and any backing file as otherwise filesystem_setup won't be able to clear up the working dir
+ if (*testreturn)
+ testreturn->get().close();
+ temph.close();
+ },
+ "check section")
+ ));
// clang-format on
auto results = permuter(boundf);