Browse Source

Actively report to syslog when waiting for mounts

pull/1159/head
Antonio SJ Musumeci 2 years ago
parent
commit
eebd6e9eb4
  1. 3
      src/branches.cpp
  2. 128
      src/fs_wait_for_mount.cpp
  3. 18
      src/fs_wait_for_mount.hpp
  4. 11
      src/mergerfs.cpp

3
src/branches.cpp

@ -188,6 +188,9 @@ namespace l
branch.set_minfreespace(minfreespace.value()); branch.set_minfreespace(minfreespace.value());
fs::glob(glob,&paths); fs::glob(glob,&paths);
if(paths.empty())
paths.push_back(glob);
fs::realpathize(&paths); fs::realpathize(&paths);
for(auto &path : paths) for(auto &path : paths)
{ {

128
src/fs_wait_for_mount.cpp

@ -17,96 +17,116 @@
*/ */
#include "fs_wait_for_mount.hpp" #include "fs_wait_for_mount.hpp"
#include "syslog.hpp"
#include <thread> #include <thread>
#include <unordered_set>
namespace fs
{
typedef std::unordered_set<fs::Path> PathSet;
}
constexpr std::chrono::milliseconds SLEEP_DURATION = std::chrono::milliseconds(333); constexpr std::chrono::milliseconds SLEEP_DURATION = std::chrono::milliseconds(333);
template<>
struct std::hash<fs::Path>
{
std::size_t
operator()(fs::Path const &path_) const noexcept
{
return std::hash<std::string>{}(path_.string());
}
};
bool static
fs::wait_for_mount(const struct stat &src_st_, void
const ghc::filesystem::path &tgtpath_, _check_mounted(const struct stat &src_st_,
const std::chrono::milliseconds &timeout_) const fs::PathSet &tgt_paths_,
fs::PathVector *successes_,
fs::PathVector *failures_)
{ {
int rv; fs::PathVector &successes = *successes_;
std::chrono::duration<double> time_diff; fs::PathVector &failures = *failures_;
std::chrono::time_point<std::chrono::steady_clock> start_time;
start_time = std::chrono::steady_clock::now(); for(auto const &tgt_path : tgt_paths_)
while(true)
{ {
int rv;
struct stat tgt_st; struct stat tgt_st;
rv = fs::stat(tgtpath_,&tgt_st); rv = fs::stat(tgt_path,&tgt_st);
if(rv == 0) if(rv == 0)
{ {
if(tgt_st.st_dev != src_st_.st_dev) 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 static
void void
_wait_for_mount(const struct stat &src_st_, _wait_for_mount(const struct stat &src_st_,
const fs::PathVector &tgtpaths_, const fs::PathVector &tgt_paths_,
const std::chrono::milliseconds &timeout_, const std::chrono::milliseconds &timeout_)
fs::PathVector &failed_paths_)
{ {
bool rv; fs::PathVector successes;
fs::PathVector::const_iterator i; fs::PathVector failures;
std::chrono::milliseconds timeout; std::unordered_set<fs::Path> tgt_paths;
std::chrono::milliseconds diff;
std::chrono::time_point<std::chrono::steady_clock> now; std::chrono::time_point<std::chrono::steady_clock> now;
std::chrono::time_point<std::chrono::steady_clock> start_time; std::chrono::time_point<std::chrono::steady_clock> deadline;
timeout = timeout_; tgt_paths.insert(tgt_paths_.begin(),tgt_paths_.end());
now = start_time = std::chrono::steady_clock::now(); now = std::chrono::steady_clock::now();
for(auto i = tgtpaths_.begin(); i != tgtpaths_.end(); ++i) deadline = now + timeout_;
{
diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
timeout -= diff;
rv = fs::wait_for_mount(src_st_,*i,timeout); while(true)
if(rv == false) {
failed_paths_.push_back(*i); 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(); 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 void
fs::wait_for_mount(const ghc::filesystem::path &srcpath_, fs::wait_for_mount(const fs::Path &src_path_,
const fs::PathVector &tgtpaths_, const fs::PathVector &tgt_paths_,
const std::chrono::milliseconds &timeout_, const std::chrono::milliseconds &timeout_)
fs::PathVector &failed_paths_)
{ {
int rv; int rv;
struct stat src_st; struct stat src_st;
rv = fs::stat(srcpath_,&src_st); rv = fs::stat(src_path_,&src_st);
if(rv == -1) 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_);
} }

18
src/fs_wait_for_mount.hpp

@ -29,22 +29,8 @@
namespace fs namespace fs
{ {
typedef std::vector<ghc::filesystem::path> PathVector;
bool
wait_for_mount(const struct stat &st,
const ghc::filesystem::path &tgtpath,
const std::chrono::milliseconds &timeout);
void void
wait_for_mount(const struct stat &st, wait_for_mount(const fs::Path &srcpath,
const fs::PathVector &tgtpaths, const fs::PathVector &tgtpaths,
const std::chrono::milliseconds &timeout, 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);
} }

11
src/mergerfs.cpp

@ -156,7 +156,6 @@ namespace l
wait_for_mount(const Config::Read &cfg_) wait_for_mount(const Config::Read &cfg_)
{ {
fs::PathVector paths; fs::PathVector paths;
fs::PathVector failed;
std::chrono::milliseconds timeout; std::chrono::milliseconds timeout;
paths = cfg_->branches->to_paths(); paths = cfg_->branches->to_paths();
@ -167,15 +166,7 @@ namespace l
timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000); timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000);
fs::wait_for_mount((std::string)cfg_->mountpoint, fs::wait_for_mount((std::string)cfg_->mountpoint,
paths, paths,
timeout, 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());
} }
static static

|||||||
100:0
Loading…
Cancel
Save