diff --git a/src/branches.cpp b/src/branches.cpp index ca087d04..a69f5327 100644 --- a/src/branches.cpp +++ b/src/branches.cpp @@ -188,6 +188,9 @@ namespace l branch.set_minfreespace(minfreespace.value()); fs::glob(glob,&paths); + if(paths.empty()) + paths.push_back(glob); + fs::realpathize(&paths); for(auto &path : paths) { diff --git a/src/fs_wait_for_mount.cpp b/src/fs_wait_for_mount.cpp index 35efd7d9..b943fad7 100644 --- a/src/fs_wait_for_mount.cpp +++ b/src/fs_wait_for_mount.cpp @@ -17,96 +17,116 @@ */ #include "fs_wait_for_mount.hpp" +#include "syslog.hpp" #include +#include + + +namespace fs +{ + typedef std::unordered_set PathSet; +} constexpr std::chrono::milliseconds SLEEP_DURATION = std::chrono::milliseconds(333); +template<> +struct std::hash +{ + std::size_t + operator()(fs::Path const &path_) const noexcept + { + return std::hash{}(path_.string()); + } +}; -bool -fs::wait_for_mount(const struct stat &src_st_, - const ghc::filesystem::path &tgtpath_, - const std::chrono::milliseconds &timeout_) +static +void +_check_mounted(const struct stat &src_st_, + const fs::PathSet &tgt_paths_, + fs::PathVector *successes_, + fs::PathVector *failures_) { - int rv; - std::chrono::duration time_diff; - std::chrono::time_point start_time; + fs::PathVector &successes = *successes_; + fs::PathVector &failures = *failures_; - start_time = std::chrono::steady_clock::now(); - while(true) + for(auto const &tgt_path : tgt_paths_) { + int rv; struct stat tgt_st; - rv = fs::stat(tgtpath_,&tgt_st); + rv = fs::stat(tgt_path,&tgt_st); if(rv == 0) { if(tgt_st.st_dev != src_st_.st_dev) - return true; + successes.push_back(tgt_path); + else + failures.push_back(tgt_path); + } + else + { + failures.push_back(tgt_path); } - - time_diff = (std::chrono::steady_clock::now() - start_time); - if(time_diff > timeout_) - return false; - - std::this_thread::sleep_for(SLEEP_DURATION); } - - return false; } static void _wait_for_mount(const struct stat &src_st_, - const fs::PathVector &tgtpaths_, - const std::chrono::milliseconds &timeout_, - fs::PathVector &failed_paths_) + const fs::PathVector &tgt_paths_, + const std::chrono::milliseconds &timeout_) { - bool rv; - fs::PathVector::const_iterator i; - std::chrono::milliseconds timeout; - std::chrono::milliseconds diff; + fs::PathVector successes; + fs::PathVector failures; + std::unordered_set tgt_paths; std::chrono::time_point now; - std::chrono::time_point start_time; + std::chrono::time_point deadline; - timeout = timeout_; - now = start_time = std::chrono::steady_clock::now(); - for(auto i = tgtpaths_.begin(); i != tgtpaths_.end(); ++i) - { - diff = std::chrono::duration_cast(now - start_time); - timeout -= diff; + tgt_paths.insert(tgt_paths_.begin(),tgt_paths_.end()); + now = std::chrono::steady_clock::now(); + deadline = now + timeout_; - rv = fs::wait_for_mount(src_st_,*i,timeout); - if(rv == false) - failed_paths_.push_back(*i); + while(true) + { + if(tgt_paths.empty()) + break; + if(now >= deadline) + break; + + successes.clear(); + failures.clear(); + ::_check_mounted(src_st_,tgt_paths,&successes,&failures); + for(auto const &path : successes) + { + tgt_paths.erase(path); + syslog_info("%s is mounted",path.string().c_str()); + } + std::this_thread::sleep_for(SLEEP_DURATION); now = std::chrono::steady_clock::now(); } -} - -void -fs::wait_for_mount(const struct stat &src_st_, - const fs::PathVector &tgtpaths_, - const std::chrono::milliseconds &timeout_, - fs::PathVector &failed_paths_) -{ - if(tgtpaths_.empty()) - return; - _wait_for_mount(src_st_,tgtpaths_,timeout_,failed_paths_); + for(auto const &path : failures) + syslog_notice("%s not mounted within timeout",path.string().c_str()); + if(!failures.empty()) + syslog_warning("Continuing to mount mergerfs despite %u branches not " + "being different from the mountpoint filesystem", + failures.size()); } void -fs::wait_for_mount(const ghc::filesystem::path &srcpath_, - const fs::PathVector &tgtpaths_, - const std::chrono::milliseconds &timeout_, - fs::PathVector &failed_paths_) +fs::wait_for_mount(const fs::Path &src_path_, + const fs::PathVector &tgt_paths_, + const std::chrono::milliseconds &timeout_) { int rv; struct stat src_st; - rv = fs::stat(srcpath_,&src_st); + rv = fs::stat(src_path_,&src_st); if(rv == -1) - return; + return syslog_error("Error stat'ing mount path: %s (%s)", + src_path_.c_str(), + strerror(errno)); - fs::wait_for_mount(src_st,tgtpaths_,timeout_,failed_paths_); + ::_wait_for_mount(src_st,tgt_paths_,timeout_); } diff --git a/src/fs_wait_for_mount.hpp b/src/fs_wait_for_mount.hpp index d3dfe12b..c4a30026 100644 --- a/src/fs_wait_for_mount.hpp +++ b/src/fs_wait_for_mount.hpp @@ -29,22 +29,8 @@ namespace fs { - typedef std::vector PathVector; - - bool - wait_for_mount(const struct stat &st, - const ghc::filesystem::path &tgtpath, - const std::chrono::milliseconds &timeout); - void - wait_for_mount(const struct stat &st, + wait_for_mount(const fs::Path &srcpath, const fs::PathVector &tgtpaths, - const std::chrono::milliseconds &timeout, - fs::PathVector &failed_paths); - - void - wait_for_mount(const ghc::filesystem::path &srcpath, - const fs::PathVector &tgtpaths, - const std::chrono::milliseconds &timeout, - fs::PathVector &failed_paths); + const std::chrono::milliseconds &timeout); } diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 96fb82c8..39d7cde9 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -156,7 +156,6 @@ namespace l wait_for_mount(const Config::Read &cfg_) { fs::PathVector paths; - fs::PathVector failed; std::chrono::milliseconds timeout; paths = cfg_->branches->to_paths(); @@ -167,15 +166,7 @@ namespace l timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000); fs::wait_for_mount((std::string)cfg_->mountpoint, paths, - timeout, - failed); - for(auto &path : failed) - syslog_warning("Branch %s was not mounted within timeout", - path.c_str()); - if(failed.size()) - syslog_warning("Continuing to mount mergerfs despite %u branches not " - "being different from the mountpoint filesystem", - failed.size()); + timeout); } static