diff options
author | Jenkins nedprod CI <jenkins-nedprod@europe5.nedproductions.biz> | 2020-07-09 02:00:12 +0300 |
---|---|---|
committer | Jenkins nedprod CI <jenkins-nedprod@europe5.nedproductions.biz> | 2020-07-09 02:00:12 +0300 |
commit | 9050f5c8446e147ea5ed1f1470da6cd40f8d883a (patch) | |
tree | a9bd37df2f06fde417df9926a0acc59a3eb0f68c | |
parent | d78c59d3d968f025fca67103cd90a5c08e13dc25 (diff) | |
parent | 87e87e998e59703610b8a17e5a7e5d12cb3d1242 (diff) |
Merged from develop branch as CDash reports all green
-rw-r--r-- | include/llfio/revision.hpp | 6 | ||||
-rw-r--r-- | include/llfio/v2.0/algorithm/clone.hpp | 35 | ||||
-rw-r--r-- | include/llfio/v2.0/detail/impl/clone.ipp | 25 |
3 files changed, 51 insertions, 15 deletions
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp index bafbaa31..bbd5205c 100644 --- a/include/llfio/revision.hpp +++ b/include/llfio/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 LLFIO_PREVIOUS_COMMIT_REF 07068de54ae723c8e4e3d9c91fde97ee378ccad2 -#define LLFIO_PREVIOUS_COMMIT_DATE "2020-07-03 19:01:39 +00:00" -#define LLFIO_PREVIOUS_COMMIT_UNIQUE 07068de5 +#define LLFIO_PREVIOUS_COMMIT_REF cc0e5e5ad9c04b23aadfc8eed704b2c2194292ea +#define LLFIO_PREVIOUS_COMMIT_DATE "2020-07-08 12:34:00 +00:00" +#define LLFIO_PREVIOUS_COMMIT_UNIQUE cc0e5e5a diff --git a/include/llfio/v2.0/algorithm/clone.hpp b/include/llfio/v2.0/algorithm/clone.hpp index fbfade35..570ef089 100644 --- a/include/llfio/v2.0/algorithm/clone.hpp +++ b/include/llfio/v2.0/algorithm/clone.hpp @@ -45,7 +45,10 @@ namespace algorithm the original to the clone/copy as possible. \param force_copy_now Parameter to pass to `file_handle::clone_extents()` to force extents to be copied now, not copy-on-write lazily later. - \param creation How to create the destination file handle. + \param creation How to create the destination file handle. NOTE that if this + is NOT `always_new`, if the destination has identical maximum extent and + timestamps (and permissions on POSIX) to the source, it is NOT copied, and + zero is returned. \param d Deadline by which to complete the operation. Firstly, a `file_handle` is constructed at the destination using `creation`, @@ -76,6 +79,7 @@ namespace algorithm bool preserve_timestamps = true, bool force_copy_now = false, file_handle::creation creation = file_handle::creation::always_new, deadline d = {}) noexcept; + #if 0 #ifdef _MSC_VER #pragma warning(push) @@ -98,17 +102,24 @@ namespace algorithm clone, //!< File content is to be extents cloned when possible copy, //!< File content is to copied now into its destination link, //!< File content is to be hard linked into its destination - symlink //! File content is to be symlinked into its destination - } op; + symlink //!< File content is to be symlinked into its destination + } op{op_t::clone}; + bool always_create_new_files{false}; bool follow_symlinks{false}; std::chrono::steady_clock::duration timeout{std::chrono::seconds(10)}; std::chrono::steady_clock::time_point begin; + //! Default constructor + clone_copy_link_symlink_visitor() = default; //! Constructs an instance with the default timeout of ten seconds. - constexpr clone_copy_link_symlink_visitor(op_t _op, bool _follow_symlinks = false) : op(_op), follow_symlinks(_follow_symlinks) {} + constexpr clone_copy_link_symlink_visitor(op_t _op, bool _always_create_new_files = false, bool _follow_symlinks = false) : op(_op), always_create_new_files(_always_create_new_files), follow_symlinks(_follow_symlinks) {} //! Constructs an instance with the specified timeout. - constexpr explicit clone_copy_link_symlink_visitor(op_t _op, std::chrono::steady_clock::duration _timeout, bool _follow_symlinks = false) - : op(_op), follow_symlinks(_follow_symlinks), timeout(_timeout) + constexpr explicit clone_copy_link_symlink_visitor(op_t _op, std::chrono::steady_clock::duration _timeout, bool _always_create_new_files = false, + bool _follow_symlinks = false) + : op(_op) + , always_create_new_files(_always_create_new_files) + , follow_symlinks(_follow_symlinks) + , timeout(_timeout) { } @@ -149,9 +160,17 @@ namespace algorithm would exceed the free disc space on the destination volume, the destination is removed and an error code is returned comparing equal to `errc::no_space_on_device`. - Otherwise, for every file in the source, its contents are cloned with `emulate_if_unsupported = true` + Otherwise, for every file in the source, its contents are cloned with `clone_or_copy()` into an equivalent file in the destination. This means that the contents are either - cloned or copied to the best extent of your filesystems and kernel. + cloned or copied to the best extent of your filesystems and kernel. If failure occurs + during this stage, the destination is left as-is in a partially copied state. + + Note the default visitor parameters: Extent cloning is preferred, we do nothing + if destination file maximum extent and timestamps are identical to source, we don't + follow symlinks, instead cloning the symlink itself. + + Note also that files or directories in the destination which are not in the source + are left untouched. You should review the documentation for `algorithm::traverse()`, as this algorithm is entirely implemented using that algorithm. diff --git a/include/llfio/v2.0/detail/impl/clone.ipp b/include/llfio/v2.0/detail/impl/clone.ipp index 743f9e48..4ceb58e9 100644 --- a/include/llfio/v2.0/detail/impl/clone.ipp +++ b/include/llfio/v2.0/detail/impl/clone.ipp @@ -36,17 +36,34 @@ namespace algorithm filesystem::path destleaf_; if(destleaf.empty()) { - OUTCOME_TRY(auto &&_, src.current_path()); - if(_.empty()) + OUTCOME_TRY(destleaf_, src.current_path()); + if(destleaf_.empty()) { // Source has been deleted, so can't infer leafname return errc::no_such_file_or_directory; } - destleaf_ = std::move(_); destleaf = destleaf_; } stat_t stat(nullptr); OUTCOME_TRY(stat.fill(src)); + if(creation != file_handle::creation::always_new) + { + auto r = file_handle::file(destdir, destleaf, file_handle::mode::attr_read, file_handle::creation::open_existing); + if(r) + { + stat_t deststat(nullptr); + OUTCOME_TRY(deststat.fill(r.value())); + if((stat.st_type == deststat.st_type) && (stat.st_mtim == deststat.st_mtim) && (stat.st_ctim == deststat.st_ctim) && + (stat.st_birthtim == deststat.st_birthtim) && (stat.st_size == deststat.st_size) +#ifndef _WIN32 + && (stat.st_perms == deststat.st_perms) && (stat.st_uid == deststat.st_uid) && (stat.st_gid == deststat.st_gid) && (stat.st_rdev == deststat.st_rdev) +#endif + ) + { + return 0; // nothing copied + } + } + } OUTCOME_TRY(auto dest, file_handle::file(destdir, destleaf, file_handle::mode::write, creation, src.kernel_caching())); bool failed = true; auto undest = make_scope_exit([&]() noexcept { @@ -76,7 +93,7 @@ namespace algorithm { return errc::no_space_on_device; } - OUTCOME_TRY(auto &&copied, src.clone_extents_to(dest, d, force_copy_now, true)); + OUTCOME_TRY(auto copied, src.clone_extents_to(dest, d, force_copy_now, true)); failed = false; return copied.length; } |