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>2021-05-04 20:47:11 +0300
committerNiall Douglas (s [underscore] sourceforge {at} nedprod [dot] com) <spamtrap@nedprod.com>2021-05-04 20:47:11 +0300
commitaaac3b0b28c271a258902e16389a0e71c8fb074d (patch)
tree448a3a28165eb910851ef03d41f3339ec76a05dd
parentb1a36308e99c5477fc3791de6f9fff993099c69f (diff)
No longer have path_handle identify itself as a directory, but instead as a path. directory_handle now identifies itself as both a path and a directory. In algorithm/summarize, if fed not a directory_handle, clone a directory handle from the input.
-rw-r--r--include/llfio/v2.0/algorithm/summarize.hpp12
-rw-r--r--include/llfio/v2.0/detail/impl/posix/directory_handle.ipp2
-rw-r--r--include/llfio/v2.0/detail/impl/posix/path_handle.ipp2
-rw-r--r--include/llfio/v2.0/detail/impl/windows/directory_handle.ipp2
-rw-r--r--include/llfio/v2.0/detail/impl/windows/path_handle.ipp2
-rw-r--r--include/llfio/v2.0/handle.hpp52
-rw-r--r--include/llfio/v2.0/native_handle_type.hpp3
7 files changed, 50 insertions, 25 deletions
diff --git a/include/llfio/v2.0/algorithm/summarize.hpp b/include/llfio/v2.0/algorithm/summarize.hpp
index 8bdbe29d..df797dad 100644
--- a/include/llfio/v2.0/algorithm/summarize.hpp
+++ b/include/llfio/v2.0/algorithm/summarize.hpp
@@ -174,7 +174,7 @@ namespace algorithm
}
};
- /*! \brief Summarise the directory identified `dirh`, and everything therein.
+ /*! \brief Summarise the directory identified `topdirh`, and everything therein.
It can be useful to summarise a directory hierarchy, especially to determine how
much storage it occupies, but also how many mounted filesystems it straddles etc.
@@ -186,10 +186,10 @@ namespace algorithm
implemented entirely as header code. You should review the documentation for
`algorithm::traverse()`, as this algorithm is entirely implemented using that algorithm.
*/
- inline result<traversal_summary> summarize(const path_handle &dirh, stat_t::want want = traversal_summary::default_metadata(),
+ inline result<traversal_summary> summarize(const path_handle &topdirh, stat_t::want want = traversal_summary::default_metadata(),
summarize_visitor *visitor = nullptr, size_t threads = 0, bool force_slow_path = false) noexcept
{
- LLFIO_LOG_FUNCTION_CALL(&dirh);
+ LLFIO_LOG_FUNCTION_CALL(&topdirh);
summarize_visitor default_visitor;
if(visitor == nullptr)
{
@@ -198,6 +198,12 @@ namespace algorithm
result<traversal_summary> state(in_place_type<traversal_summary>);
state.assume_value().want = want;
directory_entry entry{{}, stat_t(nullptr)};
+ directory_handle _dirh;
+ if(!topdirh.is_directory())
+ {
+ OUTCOME_TRY(_dirh, directory_handle::directory(topdirh, {}));
+ }
+ const path_handle &dirh = _dirh.is_valid() ? _dirh : topdirh;
OUTCOME_TRY(entry.stat.fill(dirh, want));
OUTCOME_TRY(summarize_visitor::accumulate(state.assume_value(), &state.assume_value(), nullptr, entry, want));
OUTCOME_TRY(traverse(dirh, visitor, threads, &state.assume_value(), force_slow_path));
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 bd0050d6..d9bfc2be 100644
--- a/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
@@ -49,7 +49,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
result<directory_handle> ret(directory_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
LLFIO_LOG_FUNCTION_CALL(&ret);
- nativeh.behaviour |= native_handle_type::disposition::directory;
+ nativeh.behaviour |= native_handle_type::disposition::directory | native_handle_type::disposition::path;
// POSIX does not permit directory opens with O_RDWR like Windows, so silently convert to read
if(_mode == mode::attr_write)
{
diff --git a/include/llfio/v2.0/detail/impl/posix/path_handle.ipp b/include/llfio/v2.0/detail/impl/posix/path_handle.ipp
index c349cca1..47b242f5 100644
--- a/include/llfio/v2.0/detail/impl/posix/path_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/posix/path_handle.ipp
@@ -56,7 +56,7 @@ result<path_handle> path_handle::path(const path_handle &base, path_handle::path
result<path_handle> ret(in_place_type<path_handle>);
native_handle_type &nativeh = ret.value()._v;
LLFIO_LOG_FUNCTION_CALL(&ret);
- nativeh.behaviour |= native_handle_type::disposition::directory;
+ nativeh.behaviour |= native_handle_type::disposition::path;
nativeh.behaviour &= ~native_handle_type::disposition::seekable; // not seekable
int attribs = O_CLOEXEC | O_RDONLY;
#ifdef O_DIRECTORY
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 4da58a91..f8719e0c 100644
--- a/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/directory_handle.ipp
@@ -43,7 +43,7 @@ result<directory_handle> directory_handle::directory(const path_handle &base, pa
result<directory_handle> ret(directory_handle(native_handle_type(), 0, 0, _caching, flags));
native_handle_type &nativeh = ret.value()._v;
LLFIO_LOG_FUNCTION_CALL(&ret);
- nativeh.behaviour |= native_handle_type::disposition::directory;
+ nativeh.behaviour |= native_handle_type::disposition::directory | native_handle_type::disposition::path;
DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
// Trying to truncate a directory returns EISDIR rather than some internal Win32 error code uncomparable to errc
if(_creation == creation::truncate_existing)
diff --git a/include/llfio/v2.0/detail/impl/windows/path_handle.ipp b/include/llfio/v2.0/detail/impl/windows/path_handle.ipp
index bc938ad9..2d394c8f 100644
--- a/include/llfio/v2.0/detail/impl/windows/path_handle.ipp
+++ b/include/llfio/v2.0/detail/impl/windows/path_handle.ipp
@@ -81,7 +81,7 @@ result<path_handle> path_handle::path(const path_handle &base, path_handle::path
result<path_handle> ret{path_handle(native_handle_type(), caching::none, flag::none)};
native_handle_type &nativeh = ret.value()._v;
LLFIO_LOG_FUNCTION_CALL(&ret);
- nativeh.behaviour |= native_handle_type::disposition::directory;
+ nativeh.behaviour |= native_handle_type::disposition::path;
DWORD fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
// Open directory with no access requested, this is much faster than asking for access
OUTCOME_TRY(auto &&access, access_mask_from_handle_mode(nativeh, mode::none, flag::none));
diff --git a/include/llfio/v2.0/handle.hpp b/include/llfio/v2.0/handle.hpp
index 5b737a15..22046e4b 100644
--- a/include/llfio/v2.0/handle.hpp
+++ b/include/llfio/v2.0/handle.hpp
@@ -70,9 +70,10 @@ public:
attr_read = 4, //!< Ability to read attributes (FILE_READ_ATTRIBUTES|SYNCHRONIZE or O_RDONLY)
attr_write = 5, //!< Ability to read and write attributes (FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES|SYNCHRONIZE or O_RDONLY)
read = 6, //!< Ability to read (READ_CONTROL|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|SYNCHRONISE or O_RDONLY)
- write = 7, //!< Ability to read and write (READ_CONTROL|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONISE or O_RDWR)
- append = 9 //!< All mainstream OSs and CIFS guarantee this is atomic with respect to all other appenders (FILE_APPEND_DATA|SYNCHRONISE or O_APPEND)
- // NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
+ write =
+ 7, //!< Ability to read and write (READ_CONTROL|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONISE or O_RDWR)
+ append = 9 //!< All mainstream OSs and CIFS guarantee this is atomic with respect to all other appenders (FILE_APPEND_DATA|SYNCHRONISE or O_APPEND)
+ // NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
};
//! On opening, do we also create a new file or truncate an existing one?
enum class creation : unsigned char
@@ -88,14 +89,21 @@ public:
enum class caching : unsigned char // bit 0 set means safety barriers enabled
{
unchanged = 0,
- none = 1, //!< No caching whatsoever, all reads and writes come from storage (i.e. <tt>O_DIRECT|O_SYNC</tt>). Align all i/o to 4Kb boundaries for this to work. <tt>disable_safety_barriers</tt> can be used here.
- only_metadata = 2, //!< Cache reads and writes of metadata but avoid caching data (<tt>O_DIRECT</tt>), thus i/o here does not affect other cached data for other handles. Align all i/o to 4Kb boundaries for this to work.
- reads = 3, //!< Cache reads only. Writes of data and metadata do not complete until reaching storage (<tt>O_SYNC</tt>). <tt>disable_safety_barriers</tt> can be used here.
- reads_and_metadata = 5, //!< Cache reads and writes of metadata, but writes of data do not complete until reaching storage (<tt>O_DSYNC</tt>). <tt>disable_safety_barriers</tt> can be used here.
- all = 6, //!< Cache reads and writes of data and metadata so they complete immediately, sending writes to storage at some point when the kernel decides (this is the default file system caching on a system).
- safety_barriers = 7, //!< Cache reads and writes of data and metadata so they complete immediately, but issue safety barriers at certain points. See documentation for <tt>disable_safety_barriers</tt>.
- temporary = 8 //!< Cache reads and writes of data and metadata so they complete immediately, only sending any updates to storage on last handle close in the system or if memory becomes tight as this file is expected to be temporary (Windows and FreeBSD only).
- // NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
+ none =
+ 1, //!< No caching whatsoever, all reads and writes come from storage (i.e. <tt>O_DIRECT|O_SYNC</tt>). Align all i/o to 4Kb boundaries for this to work. <tt>disable_safety_barriers</tt> can be used here.
+ only_metadata =
+ 2, //!< Cache reads and writes of metadata but avoid caching data (<tt>O_DIRECT</tt>), thus i/o here does not affect other cached data for other handles. Align all i/o to 4Kb boundaries for this to work.
+ reads =
+ 3, //!< Cache reads only. Writes of data and metadata do not complete until reaching storage (<tt>O_SYNC</tt>). <tt>disable_safety_barriers</tt> can be used here.
+ reads_and_metadata =
+ 5, //!< Cache reads and writes of metadata, but writes of data do not complete until reaching storage (<tt>O_DSYNC</tt>). <tt>disable_safety_barriers</tt> can be used here.
+ all =
+ 6, //!< Cache reads and writes of data and metadata so they complete immediately, sending writes to storage at some point when the kernel decides (this is the default file system caching on a system).
+ safety_barriers =
+ 7, //!< Cache reads and writes of data and metadata so they complete immediately, but issue safety barriers at certain points. See documentation for <tt>disable_safety_barriers</tt>.
+ temporary =
+ 8 //!< Cache reads and writes of data and metadata so they complete immediately, only sending any updates to storage on last handle close in the system or if memory becomes tight as this file is expected to be temporary (Windows and FreeBSD only).
+ // NOTE: IF UPDATING THIS UPDATE THE std::ostream PRINTER BELOW!!!
};
//! Bitwise flags which can be specified
QUICKCPPLIB_BITFIELD_BEGIN(flag){
@@ -202,7 +210,9 @@ protected:
static constexpr void _set_caching(native_handle_type &nativeh, caching caching) noexcept
{
- nativeh.behaviour &= ~(native_handle_type::disposition::safety_barriers | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_temporary);
+ nativeh.behaviour &=
+ ~(native_handle_type::disposition::safety_barriers | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::cache_reads |
+ native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_temporary);
switch(caching)
{
case caching::unchanged:
@@ -217,16 +227,20 @@ protected:
nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::safety_barriers;
break;
case caching::reads_and_metadata:
- nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::safety_barriers;
+ nativeh.behaviour |=
+ native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::safety_barriers;
break;
case caching::all:
- nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_metadata;
+ nativeh.behaviour |=
+ native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_metadata;
break;
case caching::safety_barriers:
- nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::safety_barriers;
+ nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes |
+ native_handle_type::disposition::cache_metadata | native_handle_type::disposition::safety_barriers;
break;
case caching::temporary:
- nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes | native_handle_type::disposition::cache_metadata | native_handle_type::disposition::cache_temporary;
+ nativeh.behaviour |= native_handle_type::disposition::cache_reads | native_handle_type::disposition::cache_writes |
+ native_handle_type::disposition::cache_metadata | native_handle_type::disposition::cache_temporary;
break;
}
}
@@ -381,6 +395,8 @@ public:
bool is_section() const noexcept { return _v.is_section(); }
//! True if a memory allocation
bool is_allocation() const noexcept { return _v.is_allocation(); }
+ //! True if a path or a directory
+ bool is_path() const noexcept { return _v.is_path(); }
//! Kernel cache strategy used by this handle
caching kernel_caching() const noexcept
@@ -568,7 +584,7 @@ namespace detail
#pragma warning(push)
#pragma warning(disable : 4996) // the function may be unsafe
#endif
-#if (__GNUC__ >= 8) && !defined(__clang__)
+#if(__GNUC__ >= 8) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
@@ -577,7 +593,7 @@ namespace detail
// See https://godbolt.org/z/d69xzd for proof.
// So I don't know why there is a warning here about overflowing a buffer of 16!
strncpy(tls.next(dest._tls_path_id1), QUICKCPPLIB_NAMESPACE::ringbuffer_log::last190(currentpath), 190);
-#if (__GNUC__ >= 8) && !defined(__clang__)
+#if(__GNUC__ >= 8) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
diff --git a/include/llfio/v2.0/native_handle_type.hpp b/include/llfio/v2.0/native_handle_type.hpp
index 4dba6ee9..ccc9df4b 100644
--- a/include/llfio/v2.0/native_handle_type.hpp
+++ b/include/llfio/v2.0/native_handle_type.hpp
@@ -62,6 +62,7 @@ struct native_handle_type // NOLINT
process = 1U << 14U, //!< Is a child process
section = 1U << 15U, //!< Is a memory section
allocation = 1U << 16U, //!< Is a memory allocation
+ path = 1U << 17U, //!< Is a path
safety_barriers = 1U << 20U, //!< Issue write reordering barriers at various points
cache_metadata = 1U << 21U, //!< Is serving metadata from the kernel cache
@@ -181,6 +182,8 @@ struct native_handle_type // NOLINT
constexpr bool is_section() const noexcept { return (behaviour & disposition::section) ? true : false; }
//! True if a memory allocation
constexpr bool is_allocation() const noexcept { return (behaviour & disposition::allocation) ? true : false; }
+ //! True if a path or a directory
+ constexpr bool is_path() const noexcept { return (behaviour & disposition::path) ? true : false; }
};
static_assert((sizeof(void *) == 4 && sizeof(native_handle_type) == 8) || (sizeof(void *) == 8 && sizeof(native_handle_type) == 12),
"native_handle_type is not 8 or 12 bytes in size!");