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>2017-04-15 02:20:12 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2017-04-15 02:20:12 +0300
commit667fd27321e10c19d303e13822c2866962dceade (patch)
tree3af801c1bc15a0d1a235b26d5f9b92f91168433c
parent1539af5ab234cf7df38360afce48e067ad712d33 (diff)
Finished the new barrier() function for all platforms (was called sync())
Fixed all warnings on clang 5.0
m---------doc/html8
m---------include/boost/afio/boost-lite0
m---------include/boost/afio/outcome0
-rw-r--r--include/boost/afio/revision.hpp6
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp11
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp8
-rw-r--r--include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp6
-rw-r--r--include/boost/afio/v2.0/detail/impl/posix/file_handle.ipp57
-rw-r--r--include/boost/afio/v2.0/detail/impl/posix/map_handle.ipp31
-rw-r--r--include/boost/afio/v2.0/detail/impl/storage_profile.ipp6
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/file_handle.ipp20
-rw-r--r--include/boost/afio/v2.0/detail/impl/windows/map_handle.ipp19
-rw-r--r--include/boost/afio/v2.0/file_handle.hpp17
-rw-r--r--include/boost/afio/v2.0/handle.hpp47
-rw-r--r--include/boost/afio/v2.0/map_handle.hpp32
m---------test/kerneltest0
16 files changed, 184 insertions, 84 deletions
diff --git a/doc/html b/doc/html
-Subproject e62608a32e28bc6cfa714c3bebc57bed7276aac
+Subproject d91b37b3e891e4186b9cc939b8ee6b9150301cb
diff --git a/include/boost/afio/boost-lite b/include/boost/afio/boost-lite
-Subproject e52b0cd80b48fb597b6d4c49e4e2356dc8005db
+Subproject 7f6458ccfbf4c6a440824770debcf07141d4659
diff --git a/include/boost/afio/outcome b/include/boost/afio/outcome
-Subproject 6d01ab854603a38eac5752861cf0fb928d75a2f
+Subproject f0de9b1da50732f2bd43ddbad00dd6f6b7ae60f
diff --git a/include/boost/afio/revision.hpp b/include/boost/afio/revision.hpp
index 022fb3f4..f1d6f62c 100644
--- a/include/boost/afio/revision.hpp
+++ b/include/boost/afio/revision.hpp
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define BOOST_AFIO_PREVIOUS_COMMIT_REF 55c034bd8260af5a3feb9124ecf330c984e1894a
-#define BOOST_AFIO_PREVIOUS_COMMIT_DATE "2017-04-14 17:28:42 +00:00"
-#define BOOST_AFIO_PREVIOUS_COMMIT_UNIQUE 55c034bd
+#define BOOST_AFIO_PREVIOUS_COMMIT_REF 1539af5ab234cf7df38360afce48e067ad712d33
+#define BOOST_AFIO_PREVIOUS_COMMIT_DATE "2017-04-14 21:05:28 +00:00"
+#define BOOST_AFIO_PREVIOUS_COMMIT_UNIQUE 1539af5a
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
index 22c78187..4b3be0b1 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/atomic_append.hpp
@@ -195,15 +195,14 @@ namespace algorithm
else
{
// I am the first person to be using this (stale?) file, so write a new header and truncate
- ret.truncate(sizeof(header));
+ BOOST_OUTCOME_TRYV(ret.truncate(sizeof(header)));
memset(&header, 0, sizeof(header));
header.time_offset = stl11::chrono::system_clock::to_time_t(stl11::chrono::system_clock::now());
header.first_known_good = sizeof(header);
header.first_after_hole_punch = sizeof(header);
if(!skip_hashing)
header.hash = boost_lite::algorithm::hash::fast_hash::hash(((char *) &header) + 16, sizeof(header) - 16);
- BOOST_OUTCOME_TRY(_, ret.write(0, (char *) &header, sizeof(header)));
- (void) _;
+ BOOST_OUTCOME_TRYV(ret.write(0, (char *) &header, sizeof(header)));
}
// Open a shared lock on last byte in header to prevent other users zomping the file
BOOST_OUTCOME_TRY(guard, ret.lock(sizeof(header) - 1, 1, false));
@@ -249,8 +248,8 @@ namespace algorithm
// My lock request will be the file's current length or higher
BOOST_OUTCOME_TRY(my_lock_request_offset, _h.length());
{
- _h.set_append_only(true);
- auto undo = undoer([this] { _h.set_append_only(false); });
+ BOOST_OUTCOME_TRYV(_h.set_append_only(true));
+ auto undo = undoer([this] { (void) _h.set_append_only(false); });
file_handle::extent_guard append_guard;
if(_nfs_compatibility)
{
@@ -308,7 +307,7 @@ namespace algorithm
reload:
// Refresh the header and load a snapshot of everything between record_offset
// and first_known_good or -6Kb, whichever the sooner
- _read_header();
+ BOOST_OUTCOME_TRYV(_read_header());
// If there are no preceding records, we're done
if(record_offset < _header.first_known_good)
break;
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
index 18e92887..bca96337 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/lock_files.hpp
@@ -149,8 +149,10 @@ namespace algorithm
--n;
// Now 0 to n needs to be closed
for(; n > 0; n--)
- _hs[n].close(); // delete on close semantics deletes the file
- _hs[0].close();
+ {
+ (void) _hs[n].close(); // delete on close semantics deletes the file
+ }
+ (void) _hs[0].close();
}
});
for(n = 0; n < out.entities.size(); n++)
@@ -204,7 +206,7 @@ namespace algorithm
BOOST_AFIO_LOG_FUNCTION_CALL(this);
for(auto &i : _hs)
{
- i.close(); // delete on close semantics deletes the file
+ (void) i.close(); // delete on close semantics deletes the file
}
}
};
diff --git a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
index 95c1dfb5..6648fe1b 100644
--- a/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
+++ b/include/boost/afio/v2.0/algorithm/shared_fs_mutex/memory_map.hpp
@@ -266,14 +266,14 @@ namespace algorithm
else
{
// I am the first person to be using this (stale?) file, so create a new hash index file and write its path
- ret.truncate(0);
+ BOOST_OUTCOME_TRYV(ret.truncate(0));
BOOST_OUTCOME_TRY(_temph, file_handle::random_file(fixme_temporary_files_directory()));
temph = std::move(_temph);
auto temppath(temph.path());
- temph.truncate(HashIndexSize);
+ BOOST_OUTCOME_TRYV(temph.truncate(HashIndexSize));
#ifdef __linux__
// Linux appears to have a race where if you mmap for read straight after a fallocate, on read you get a SIGBUS
- temph.sync();
+ BOOST_OUTCOME_TRYV(temph.barrier());
#endif
// Write the path of my new hash index file and convert my lock to a shared one
BOOST_OUTCOME_TRYV(ret.write(0, (const char *) temppath.c_str(), temppath.native().size() * sizeof(*temppath.c_str())));
diff --git a/include/boost/afio/v2.0/detail/impl/posix/file_handle.ipp b/include/boost/afio/v2.0/detail/impl/posix/file_handle.ipp
index 14d20bca..9e66ec22 100644
--- a/include/boost/afio/v2.0/detail/impl/posix/file_handle.ipp
+++ b/include/boost/afio/v2.0/detail/impl/posix/file_handle.ipp
@@ -54,7 +54,7 @@ const fixme_path &fixme_temporary_files_directory() noexcept
if(buffer[len - 1] == '/')
buffer.resize(--len);
buffer.append("/afio_tempfile_probe_file.tmp");
- int h = open(buffer.c_str(), O_WRONLY|O_CREAT, 0666);
+ int h = open(buffer.c_str(), O_WRONLY | O_CREAT, 0666);
if(-1 != h)
{
unlink(buffer.c_str());
@@ -177,7 +177,7 @@ inline result<int> attribs_from_handle_mode_caching_and_flags(native_handle_type
result<void> file_handle::_fetch_inode() noexcept
{
stat_t s;
- BOOST_OUTCOME_TRYV(s.fill(*this, stat_t::want::dev|stat_t::want::ino));
+ BOOST_OUTCOME_TRYV(s.fill(*this, stat_t::want::dev | stat_t::want::ino));
_devid = s.st_dev;
_inode = s.st_ino;
return make_valued_result<void>();
@@ -186,7 +186,7 @@ result<void> file_handle::_fetch_inode() noexcept
inline result<void> check_inode(const file_handle &h) noexcept
{
stat_t s;
- BOOST_OUTCOME_TRYV(s.fill(h, stat_t::want::dev|stat_t::want::ino));
+ BOOST_OUTCOME_TRYV(s.fill(h, stat_t::want::dev | stat_t::want::ino));
if(s.st_dev != h.st_dev() || s.st_ino != h.st_ino())
return make_errored_result<void>(stl11::errc::no_such_file_or_directory);
return make_valued_result<void>();
@@ -224,8 +224,8 @@ result<file_handle> file_handle::temp_inode(path_type dirpath, mode _mode, flag
nativeh.behaviour |= native_handle_type::disposition::file;
#ifdef O_TMPFILE
// Linux has a special flag just for this use case
- attribs|=O_TMPFILE;
- attribs&=~O_EXCL; // allow relinking later
+ attribs |= O_TMPFILE;
+ attribs &= ~O_EXCL; // allow relinking later
const char *path_ = ret.value()._path.c_str();
nativeh.fd = ::open(path_, attribs, 0600);
if(-1 != nativeh.fd)
@@ -234,8 +234,8 @@ result<file_handle> file_handle::temp_inode(path_type dirpath, mode _mode, flag
return ret;
}
// If it failed, assume this kernel or FS doesn't support O_TMPFILE
- attribs&=~O_TMPFILE;
- attribs|=O_EXCL;
+ attribs &= ~O_TMPFILE;
+ attribs |= O_EXCL;
#endif
for(;;)
{
@@ -263,6 +263,49 @@ result<file_handle> file_handle::temp_inode(path_type dirpath, mode _mode, flag
}
}
+file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(file_handle::io_request<file_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
+{
+ BOOST_AFIO_LOG_FUNCTION_CALL(_v.fd);
+ if(d)
+ return make_errored_result<>(stl11::errc::not_supported);
+#ifdef __linux__
+ if(!wait_for_device && !and_metadata)
+ {
+ // Linux has a lovely dedicated syscall giving us exactly what we need here
+ extent_type offset = reqs.offset, bytes = 0;
+ for(const auto &req : reqs.buffers) // empty buffers means bytes = 0 which means sync entire file
+ bytes += req.second;
+ unsigned flags = SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE; // start writing all dirty pages in range now
+ if(-1 != ::sync_file_range(_v.fd, offset, bytes, flags))
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+ }
+#endif
+#if !defined(__FreeBSD__) && !defined(__APPLE__) // neither of these have fdatasync()
+ if(!and_metadata)
+ {
+ if(-1 == ::fdatasync(_v.fd))
+ return make_errored_result<>(errno);
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+ }
+#endif
+#ifdef __APPLE__
+ if(!wait_for_device)
+ {
+ // OS X fsync doesn't wait for the device to flush its buffers
+ if(-1 == ::fsync(_v.fd))
+ return make_errored_result<>(errno);
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+ }
+ // This is the fsync as on every other OS
+ if(-1 == ::fcntl(_v.fd, F_FULLFSYNC))
+ return make_errored_result<>(errno);
+#else
+ if(-1 == ::fsync(_v.fd))
+ return make_errored_result<>(errno);
+#endif
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+}
+
result<file_handle> file_handle::clone() const noexcept
{
BOOST_AFIO_LOG_FUNCTION_CALL(_v.fd);
diff --git a/include/boost/afio/v2.0/detail/impl/posix/map_handle.ipp b/include/boost/afio/v2.0/detail/impl/posix/map_handle.ipp
index 42d82a97..73a68910 100644
--- a/include/boost/afio/v2.0/detail/impl/posix/map_handle.ipp
+++ b/include/boost/afio/v2.0/detail/impl/posix/map_handle.ipp
@@ -104,10 +104,29 @@ native_handle_type map_handle::release() noexcept
return native_handle_type();
}
+map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_handle::io_request<map_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
+{
+ BOOST_AFIO_LOG_FUNCTION_CALL(_v.fd);
+ char *addr = _addr + reqs.offset;
+ extent_type bytes = 0;
+ for(const auto &req : reqs.buffers)
+ bytes += req.second;
+ int flags = (wait_for_device || and_metadata) ? MS_SYNC : MS_ASYNC;
+ if(-1 == ::msync(addr, bytes, flags))
+ return make_errored_result<>(errno);
+ if(_section->backing() && (wait_for_device || and_metadata))
+ {
+ reqs.offset += _offset;
+ return _section->backing()->barrier(std::move(reqs), wait_for_device, and_metadata, d);
+ }
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+}
+
+
inline result<void *> do_mmap(native_handle_type &nativeh, void *ataddr, section_handle *section, map_handle::size_type &bytes, map_handle::extent_type offset, section_handle::flag _flag) noexcept
{
bool have_backing = section->backing();
- int prot = 0, flags = have_backing ? MAP_SHARED : MAP_PRIVATE|MAP_ANONYMOUS;
+ int prot = 0, flags = have_backing ? MAP_SHARED : MAP_PRIVATE | MAP_ANONYMOUS;
void *addr = nullptr;
if(_flag == section_handle::flag::none)
{
@@ -115,14 +134,14 @@ inline result<void *> do_mmap(native_handle_type &nativeh, void *ataddr, section
}
else if(_flag & section_handle::flag::cow)
{
- prot |= PROT_READ|PROT_WRITE;
+ prot |= PROT_READ | PROT_WRITE;
flags &= ~MAP_SHARED;
flags |= MAP_PRIVATE;
nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable | native_handle_type::disposition::writable;
}
else if(_flag & section_handle::flag::write)
{
- prot |= PROT_READ|PROT_WRITE;
+ prot |= PROT_READ | PROT_WRITE;
nativeh.behaviour |= native_handle_type::disposition::seekable | native_handle_type::disposition::readable | native_handle_type::disposition::writable;
}
else if(_flag & section_handle::flag::read)
@@ -148,7 +167,7 @@ inline result<void *> do_mmap(native_handle_type &nativeh, void *ataddr, section
if(have_backing && (section.backing()->kernel_caching() == handle::caching::temporary))
flags |= MAP_NOSYNC;
#endif
- //printf("mmap(%p, %u, %d, %d, %d, %u)\n", ataddr, (unsigned) bytes, prot, flags, have_backing ? section->backing_native_handle().fd : -1, (unsigned) offset);
+ // printf("mmap(%p, %u, %d, %d, %d, %u)\n", ataddr, (unsigned) bytes, prot, flags, have_backing ? section->backing_native_handle().fd : -1, (unsigned) offset);
addr = ::mmap(ataddr, bytes, prot, flags, have_backing ? section->backing_native_handle().fd : -1, offset);
if(MAP_FAILED == addr)
return make_errored_result<void *>(errno);
@@ -165,7 +184,7 @@ result<map_handle> map_handle::map(section_handle &section, size_type bytes, ext
// Do NOT round up bytes to the nearest page size for backed maps, it causes an attempt to extend the file
bytes = _bytes;
}
- result<map_handle> ret(map_handle(&section));
+ result<map_handle> ret(make_valued_result<map_handle>(map_handle(&section)));
native_handle_type &nativeh = ret.get()._v;
BOOST_OUTCOME_TRY(addr, do_mmap(nativeh, nullptr, &section, bytes, offset, _flag));
ret.get()._addr = (char *) addr;
@@ -215,7 +234,7 @@ result<void> map_handle::zero(buffer_type region) noexcept
if(!region.first)
return make_errored_result<void>(stl11::errc::invalid_argument);
#ifdef MADV_REMOVE
- buffer_type page_region { (char *) utils::round_up_to_page_size((uintptr_t) region.first), utils::round_down_to_page_size(region.second) };
+ buffer_type page_region{(char *) utils::round_up_to_page_size((uintptr_t) region.first), utils::round_down_to_page_size(region.second)};
// Zero contents and punch a hole in any backing storage
if(page_region.second && -1 != ::madvise(page_region.first, page_region.second, MADV_REMOVE))
{
diff --git a/include/boost/afio/v2.0/detail/impl/storage_profile.ipp b/include/boost/afio/v2.0/detail/impl/storage_profile.ipp
index ec75d5e1..5c44a79d 100644
--- a/include/boost/afio/v2.0/detail/impl/storage_profile.ipp
+++ b/include/boost/afio/v2.0/detail/impl/storage_profile.ipp
@@ -328,7 +328,7 @@ namespace storage_profile
std::atomic<io_service::extent_type> atomic_rewrite_quantum(sp.atomic_rewrite_quantum.value);
std::atomic<bool> failed(false);
for(unsigned no = 0; no < concurrency; no++)
- readers.push_back(std::thread([size, &srch, no, &done, &atomic_rewrite_quantum, &failed] {
+ readers.push_back(std::thread([size, &srch, &done, &atomic_rewrite_quantum, &failed] {
auto _h(srch.clone());
if(!_h)
throw std::runtime_error("concurrency::atomic_rewrite_quantum: Could not open work file due to " + _h.get_error().message());
@@ -424,7 +424,7 @@ namespace storage_profile
std::atomic<io_service::extent_type> max_aligned_atomic_rewrite(sp.max_aligned_atomic_rewrite.value);
std::atomic<bool> failed(false);
for(unsigned no = 0; no < concurrency; no++)
- readers.push_back(std::thread([size, offset, &srch, no, &done, &max_aligned_atomic_rewrite, &failed] {
+ readers.push_back(std::thread([size, offset, &srch, &done, &max_aligned_atomic_rewrite, &failed] {
auto _h(srch.clone());
if(!_h)
throw std::runtime_error("concurrency::atomic_rewrite_quantum: Could not open work file due to " + _h.get_error().message());
@@ -532,7 +532,7 @@ namespace storage_profile
std::atomic<io_service::extent_type> atomic_rewrite_offset_boundary(sp.atomic_rewrite_offset_boundary.value);
std::atomic<bool> failed(false);
for(unsigned no = 0; no < concurrency; no++)
- readers.push_back(std::thread([size, offset, &srch, no, &done, &atomic_rewrite_offset_boundary, &failed] {
+ readers.push_back(std::thread([size, offset, &srch, &done, &atomic_rewrite_offset_boundary, &failed] {
auto _h(srch.clone());
if(!_h)
throw std::runtime_error("concurrency::atomic_rewrite_offset_boundary: Could not open work file due to " + _h.get_error().message());
diff --git a/include/boost/afio/v2.0/detail/impl/windows/file_handle.ipp b/include/boost/afio/v2.0/detail/impl/windows/file_handle.ipp
index d7a7c779..879d63f6 100644
--- a/include/boost/afio/v2.0/detail/impl/windows/file_handle.ipp
+++ b/include/boost/afio/v2.0/detail/impl/windows/file_handle.ipp
@@ -116,7 +116,7 @@ const fixme_path &fixme_temporary_files_directory() noexcept
result<void> file_handle::_fetch_inode() noexcept
{
stat_t s;
- BOOST_OUTCOME_TRYV(s.fill(*this, stat_t::want::dev|stat_t::want::ino));
+ BOOST_OUTCOME_TRYV(s.fill(*this, stat_t::want::dev | stat_t::want::ino));
_devid = s.st_dev;
_inode = s.st_ino;
return make_valued_result<void>();
@@ -217,13 +217,14 @@ result<file_handle> file_handle::temp_inode(path_type dirpath, mode _mode, flag
}
}
-file_handle::io_result<file_handle::const_buffers_type> file_handle::sync(file_handle::io_request<file_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
+file_handle::io_result<file_handle::const_buffers_type> file_handle::barrier(file_handle::io_request<file_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
{
windows_nt_kernel::init();
using namespace windows_nt_kernel;
BOOST_AFIO_LOG_FUNCTION_CALL(_v.h);
if(d && !_v.is_overlapped())
return make_errored_result<>(stl11::errc::not_supported);
+ BOOST_AFIO_WIN_DEADLINE_TO_SLEEP_INIT(d);
OVERLAPPED ol;
memset(&ol, 0, sizeof(ol));
IO_STATUS_BLOCK *isb = (IO_STATUS_BLOCK *) &ol;
@@ -236,25 +237,18 @@ file_handle::io_result<file_handle::const_buffers_type> file_handle::sync(file_h
NtFlushBuffersFileEx(_v.h, flags, isb);
if(_v.is_overlapped())
{
- if(STATUS_TIMEOUT == ntwait(_v.h, isb, d))
+ if(STATUS_TIMEOUT == ntwait(_v.h, ol, d))
{
CancelIoEx(_v.h, &ol);
BOOST_AFIO_WIN_DEADLINE_TO_TIMEOUT(void, d);
}
}
- if(STATUS_SUCCESS != isb.Status)
- return make_errored_result_nt<void>(isb.Status, last190(_path.u8string()));
- BOOST_OUTCOME_TRY(length, this->length());
- for(size_t n = 0; n < reqs.buffers.size(); n++)
- {
- reqs.buffers[n].second = !n ? length : 0;
- }
- return io_handle::io_result<BuffersType>(std::move(reqs.buffers));
+ if(STATUS_SUCCESS != isb->Status)
+ return make_errored_result_nt<void>(isb->Status, last190(_path.u8string()));
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
}
-
-
result<file_handle> file_handle::clone() const noexcept
{
BOOST_AFIO_LOG_FUNCTION_CALL(_v.h);
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 66af6696..123251c9 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
@@ -170,6 +170,23 @@ native_handle_type map_handle::release() noexcept
return native_handle_type();
}
+map_handle::io_result<map_handle::const_buffers_type> map_handle::barrier(map_handle::io_request<map_handle::const_buffers_type> reqs, bool wait_for_device, bool and_metadata, deadline d) noexcept
+{
+ BOOST_AFIO_LOG_FUNCTION_CALL(_v.h);
+ char *addr = _addr + reqs.offset;
+ extent_type bytes = 0;
+ for(const auto &req : reqs.buffers)
+ bytes += req.second;
+ if(!FlushViewOfFile(addr, (SIZE_T) bytes))
+ return make_errored_result<>(GetLastError());
+ if(_section->backing() && (wait_for_device || and_metadata))
+ {
+ reqs.offset += _offset;
+ return _section->backing()->barrier(std::move(reqs), wait_for_device, and_metadata, d);
+ }
+ return io_handle::io_result<const_buffers_type>(std::move(reqs.buffers));
+}
+
result<map_handle> map_handle::map(section_handle &section, size_type bytes, extent_type offset, section_handle::flag _flag) noexcept
{
@@ -180,7 +197,7 @@ result<map_handle> map_handle::map(section_handle &section, size_type bytes, ext
// Do NOT round up bytes to the nearest page size for backed maps, it causes an attempt to extend the file
bytes = utils::round_up_to_page_size(bytes);
}
- result<map_handle> ret(map_handle(io_handle(), &section));
+ result<map_handle> ret(make_valued_result<map_handle>(map_handle(&section)));
native_handle_type &nativeh = ret.get()._v;
ULONG allocation = 0, prot = 0;
PVOID addr = 0;
diff --git a/include/boost/afio/v2.0/file_handle.hpp b/include/boost/afio/v2.0/file_handle.hpp
index a24b8251..42798ad6 100644
--- a/include/boost/afio/v2.0/file_handle.hpp
+++ b/include/boost/afio/v2.0/file_handle.hpp
@@ -115,7 +115,12 @@ public:
{
}
//! Implicit move construction of file_handle permitted
- file_handle(file_handle &&o) noexcept : io_handle(std::move(o)), _devid(o._devid), _inode(o._inode), _path(std::move(o._path)), _service(o._service) { o._devid = 0; o._inode = 0; o._service = nullptr; }
+ file_handle(file_handle &&o) noexcept : io_handle(std::move(o)), _devid(o._devid), _inode(o._inode), _path(std::move(o._path)), _service(o._service)
+ {
+ o._devid = 0;
+ o._inode = 0;
+ o._service = nullptr;
+ }
//! Explicit conversion from handle and io_handle permitted
explicit file_handle(handle &&o, path_type path, dev_t devid, ino_t inode) noexcept : io_handle(std::move(o)), _devid(devid), _inode(inode), _path(std::move(path)), _service(nullptr) {}
//! Move assignment of file_handle permitted
@@ -202,7 +207,13 @@ public:
dev_t st_dev() const noexcept { return _devid; }
//! Unless `flag::disable_safety_unlinks` is set, the inode of the file when opened. When combined with st_dev(), forms a unique identifer on this system
ino_t st_ino() const noexcept { return _inode; }
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept override { unique_id_type ret(nullptr); ret.as_longlongs[0] = _devid; ret.as_longlongs[1] = _inode; return ret; }
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept override
+ {
+ unique_id_type ret(nullptr);
+ ret.as_longlongs[0] = _devid;
+ ret.as_longlongs[1] = _inode;
+ return ret;
+ }
BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC path_type path() const noexcept override { return _path; }
BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override
{
@@ -213,7 +224,7 @@ public:
}
return io_handle::close();
}
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> sync(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
/*! Clone this handle (copy constructor is disabled to avoid accidental copying)
diff --git a/include/boost/afio/v2.0/handle.hpp b/include/boost/afio/v2.0/handle.hpp
index e3a63342..82167f34 100644
--- a/include/boost/afio/v2.0/handle.hpp
+++ b/include/boost/afio/v2.0/handle.hpp
@@ -38,7 +38,7 @@ DEALINGS IN THE SOFTWARE.
#include "../boost-lite/include/uint128.hpp"
#include <algorithm> // for std::count
-#include <utility> // for pair<>
+#include <utility> // for pair<>
//! \file handle.hpp Provides handle
@@ -198,7 +198,12 @@ public:
}
//! A unique identifier for this handle in this process (native handle). Subclasses like `file_handle` make this a unique identifier across the entire system.
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept { unique_id_type ret(nullptr); ret.as_longlongs[0] = _v._init; return ret; }
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC unique_id_type unique_id() const noexcept
+ {
+ unique_id_type ret(nullptr);
+ ret.as_longlongs[0] = _v._init;
+ return ret;
+ }
//! The path this handle refers to, if any
BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC path_type path() const noexcept { return path_type(); }
//! Immediately close the native handle type managed by this handle
@@ -462,32 +467,38 @@ public:
return *v.data();
}
- /*! \brief Issue a write reordering barrier for preceding writes such that they will all be issued
- to storage before any writes after the barrier.
+ /*! \brief Issue a write reordering barrier such that writes preceding the barrier will reach storage
+ before writes after this barrier.
+
+ \warning **Assume that this call is a no-op**. It is not reliably implemented in many common use cases,
+ for example if your code is running inside a LXC container, or if the user has mounted the filing
+ system with non-default options. Instead open the handle with `caching::reads` which means that all
+ writes form a strict sequential order not completing until acknowledged by the storage device.
+ Filing system can and do use different algorithms to give much better performance with `caching::reads`,
+ some (e.g. ZFS) spectacularly better.
+
+ \warning Let me repeat again: consider this call to be a **hint** to poke the kernel with a stick to
+ go start to do some work sooner rather than later. It may be ignored entirely.
- \warning This call really is for people with deep understanding of individual filing systems,
- and unless you **really** know what you are doing, do NOT use this call as it is false security.
- Instead open the handle with `caching::reads`, that will get you true durable write ordering, plus the
- filing system can use different algorithms to give much better performance.
-
- \warning For portability, you can only assume that sync()'s are write ordered for a single handle
- instance. You cannot assume that sync() write orders across multiple handles to the same inode, or
+ \warning For portability, you can only assume that barriers write order for a single handle
+ instance. You cannot assume that barriers write order across multiple handles to the same inode, or
across processes.
- \return The buffers synced, which may not be the buffers input. The size of each scatter-gather
- buffer is updated with the number of bytes of that buffer synced.
- \param reqs A scatter-gather and offset request. May be ignored on some platforms.
+ \return The buffers barriered, which may not be the buffers input. The size of each scatter-gather
+ buffer is updated with the number of bytes of that buffer barriered.
+ \param reqs A scatter-gather and offset request for what range to barrier. May be ignored on some platforms
+ which always write barrier the entire file. Supplying a default initialised reqs write barriers the entire file.
\param wait_for_device True if you want the call to wait until data reaches storage and that storage
- has acknowledged the data is physically written.
- \param and_metadata True if you want the call to sync the metadata for retrieving writes until now too.
+ has acknowledged the data is physically written. Slow.
+ \param and_metadata True if you want the call to sync the metadata for retrieving the writes before the
+ barrier after a sudden power loss event. Slow.
\param d An optional deadline by which the i/o must complete, else it is cancelled.
Note function may return significantly after this deadline if the i/o takes long to cancel.
- has confirmed that the data is written before returning.
\errors Any of the values POSIX fdatasync() or Windows NtFlushBuffersFileEx() can return.
\mallocs None.
*/
//[[bindlib::make_free]]
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> sync(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept = 0;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept = 0;
/*! \class extent_guard
\brief RAII holder a locked extent of bytes in a file.
diff --git a/include/boost/afio/v2.0/map_handle.hpp b/include/boost/afio/v2.0/map_handle.hpp
index f65b092a..cfc2b38c 100644
--- a/include/boost/afio/v2.0/map_handle.hpp
+++ b/include/boost/afio/v2.0/map_handle.hpp
@@ -201,19 +201,19 @@ protected:
extent_type _offset;
size_type _length;
-public:
- //! Default constructor
- map_handle()
- : io_handle()
- , _section(nullptr)
+ explicit map_handle(section_handle *section)
+ : _section(section)
, _addr(nullptr)
, _offset(0)
, _length(0)
{
}
- //! Construct from these parameters
- explicit map_handle(section_handle *section)
- : _section(section)
+
+public:
+ //! Default constructor
+ map_handle()
+ : io_handle()
+ , _section(nullptr)
, _addr(nullptr)
, _offset(0)
, _length(0)
@@ -244,10 +244,10 @@ public:
}
//! Unmap the mapped view.
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC result<void> close() noexcept override;
//! Releases the mapped view, but does NOT release the native handle.
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept;
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> sync(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC native_handle_type release() noexcept override;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> barrier(io_request<const_buffers_type> reqs = io_request<const_buffers_type>(), bool wait_for_device = false, bool and_metadata = false, deadline d = deadline()) noexcept override;
/*! Create a memory mapped view of a backing storage.
@@ -287,7 +287,11 @@ public:
//! Ask the system to begin to asynchronously prefetch the span of memory regions given, returning the regions actually prefetched. Note that on Windows 7 or earlier the system call to implement this was not available, and so you will see an empty span returned.
static result<span<buffer_type>> prefetch(span<buffer_type> regions) noexcept;
//! \overload
- static result<buffer_type> prefetch(buffer_type region) noexcept { BOOST_OUTCOME_TRY(ret, prefetch(span<buffer_type>(&region, 1))); return *ret.data(); }
+ static result<buffer_type> prefetch(buffer_type region) noexcept
+ {
+ BOOST_OUTCOME_TRY(ret, prefetch(span<buffer_type>(&region, 1)));
+ return *ret.data();
+ }
/*! 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.
@@ -309,7 +313,7 @@ public:
\mallocs None.
*/
//[[bindlib::make_free]]
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<buffers_type> read(io_request<buffers_type> reqs, deadline d = deadline()) noexcept override;
using io_handle::read;
/*! \brief Write data to the mapped view.
@@ -322,7 +326,7 @@ public:
\mallocs None.
*/
//[[bindlib::make_free]]
- BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept;
+ BOOST_AFIO_HEADERS_ONLY_VIRTUAL_SPEC io_result<const_buffers_type> write(io_request<const_buffers_type> reqs, deadline d = deadline()) noexcept override;
using io_handle::write;
};
diff --git a/test/kerneltest b/test/kerneltest
-Subproject 212676fdc56d621e80a69a6935aa06eff962551
+Subproject e5651599c6e1bfe497fa79be9f94ba379438987