Skip to content

Commit

Permalink
No longer have path_handle identify itself as a directory, but instea…
Browse files Browse the repository at this point in the history
…d 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.
  • Loading branch information
ned14 committed May 4, 2021
1 parent b1a3630 commit aaac3b0
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 25 deletions.
12 changes: 9 additions & 3 deletions include/llfio/v2.0/algorithm/summarize.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
{
Expand All @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion include/llfio/v2.0/detail/impl/posix/directory_handle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
2 changes: 1 addition & 1 deletion include/llfio/v2.0/detail/impl/posix/path_handle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion include/llfio/v2.0/detail/impl/windows/path_handle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
52 changes: 34 additions & 18 deletions include/llfio/v2.0/handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ class LLFIO_DECL handle
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
Expand All @@ -88,14 +89,21 @@ class LLFIO_DECL handle
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){
Expand Down Expand Up @@ -202,7 +210,9 @@ class LLFIO_DECL handle

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:
Expand All @@ -217,16 +227,20 @@ class LLFIO_DECL handle
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;
}
}
Expand Down Expand Up @@ -381,6 +395,8 @@ class LLFIO_DECL handle
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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 3 additions & 0 deletions include/llfio/v2.0/native_handle_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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!");
Expand Down

0 comments on commit aaac3b0

Please sign in to comment.