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
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<double> time_diff;
std::chrono::time_point<std::chrono::steady_clock> 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; 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 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<fs::Path> tgt_paths;
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_;
now = start_time = std::chrono::steady_clock::now();
for(auto i = tgtpaths_.begin(); i != tgtpaths_.end(); ++i)
{
diff = std::chrono::duration_cast<std::chrono::milliseconds>(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(); 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_,
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; 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,
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);
} }

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,
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 static

Loading…
Cancel
Save