mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-04-24 14:04:05 +08:00
Improve mount waiting
Adds user.mergerfs.branch and user.mergerfs.branch_mounts_here Adds .mergerfs.branch and .mergerfs.branch_mounts_here files.
This commit is contained in:
parent
212681ddc5
commit
6ead015a1b
37
src/fs_mounts.cpp
Normal file
37
src/fs_mounts.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "fs_mounts.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <mntent.h>
|
||||
|
||||
#ifdef __linux__
|
||||
void
|
||||
fs::mounts(std::vector<fs::mount_t> &mounts_)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = setmntent("/proc/mounts","r");
|
||||
if(f == NULL)
|
||||
return;
|
||||
|
||||
struct mntent *entry;
|
||||
while((entry = getmntent(f)) != NULL)
|
||||
{
|
||||
fs::mount_t m;
|
||||
|
||||
m.dir = entry->mnt_dir;
|
||||
m.fsname = entry->mnt_fsname;
|
||||
m.type = entry->mnt_type;
|
||||
m.opts = entry->mnt_opts;
|
||||
|
||||
mounts_.emplace_back(std::move(m));
|
||||
}
|
||||
|
||||
endmntent(f);
|
||||
}
|
||||
#else
|
||||
void
|
||||
fs::mounts(std::vector<fs::mount_t> &mounts_)
|
||||
{
|
||||
}
|
||||
#endif
|
18
src/fs_mounts.hpp
Normal file
18
src/fs_mounts.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "ghc/filesystem.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fs
|
||||
{
|
||||
struct mount_t
|
||||
{
|
||||
ghc::filesystem::path dir;
|
||||
std::string fsname;
|
||||
std::string type;
|
||||
std::string opts;
|
||||
};
|
||||
|
||||
void mounts(std::vector<fs::mount_t> &mount);
|
||||
}
|
@ -19,6 +19,10 @@
|
||||
#include "fs_wait_for_mount.hpp"
|
||||
#include "syslog.hpp"
|
||||
|
||||
#include "fs_exists.hpp"
|
||||
#include "fs_lstat.hpp"
|
||||
#include "fs_lgetxattr.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <thread>
|
||||
#include <unordered_set>
|
||||
@ -44,6 +48,40 @@ namespace std
|
||||
};
|
||||
}
|
||||
|
||||
static
|
||||
bool
|
||||
_branch_is_mounted(const struct stat &src_st_,
|
||||
const fs::Path &branch_path_)
|
||||
{
|
||||
int rv;
|
||||
struct stat st;
|
||||
fs::Path filepath;
|
||||
|
||||
rv = fs::lgetxattr(branch_path_,"user.mergerfs.branch",NULL,0);
|
||||
if(rv != -1)
|
||||
return true;
|
||||
|
||||
filepath = branch_path_ / ".mergerfs.branch";
|
||||
rv = fs::exists(filepath);
|
||||
if(rv)
|
||||
return true;
|
||||
|
||||
rv = fs::lgetxattr(branch_path_,"user.mergerfs.branch_mounts_here",NULL,0);
|
||||
if(rv != -1)
|
||||
return false;
|
||||
|
||||
filepath = branch_path_ / ".mergerfs.branch_mounts_here";
|
||||
rv = fs::exists(filepath);
|
||||
if(rv)
|
||||
return false;
|
||||
|
||||
rv = fs::lstat(branch_path_,&st);
|
||||
if(rv == 0)
|
||||
return (st.st_dev != src_st_.st_dev);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
_check_mounted(const struct stat &src_st_,
|
||||
@ -56,21 +94,13 @@ _check_mounted(const struct stat &src_st_,
|
||||
|
||||
for(auto const &tgt_path : tgt_paths_)
|
||||
{
|
||||
int rv;
|
||||
struct stat tgt_st;
|
||||
bool mounted;
|
||||
|
||||
rv = fs::stat(tgt_path,&tgt_st);
|
||||
if(rv == 0)
|
||||
{
|
||||
if(tgt_st.st_dev != src_st_.st_dev)
|
||||
successes.push_back(tgt_path);
|
||||
else
|
||||
failures.push_back(tgt_path);
|
||||
}
|
||||
mounted = ::_branch_is_mounted(src_st_,tgt_path);
|
||||
if(mounted)
|
||||
successes.push_back(tgt_path);
|
||||
else
|
||||
{
|
||||
failures.push_back(tgt_path);
|
||||
}
|
||||
failures.push_back(tgt_path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,6 +110,7 @@ _wait_for_mount(const struct stat &src_st_,
|
||||
const fs::PathVector &tgt_paths_,
|
||||
const std::chrono::milliseconds &timeout_)
|
||||
{
|
||||
bool first_loop;
|
||||
fs::PathVector successes;
|
||||
fs::PathVector failures;
|
||||
std::unordered_set<fs::Path> tgt_paths;
|
||||
@ -90,6 +121,7 @@ _wait_for_mount(const struct stat &src_st_,
|
||||
now = std::chrono::steady_clock::now();
|
||||
deadline = now + timeout_;
|
||||
|
||||
first_loop = true;
|
||||
while(true)
|
||||
{
|
||||
if(tgt_paths.empty())
|
||||
@ -100,12 +132,19 @@ _wait_for_mount(const struct stat &src_st_,
|
||||
successes.clear();
|
||||
failures.clear();
|
||||
::_check_mounted(src_st_,tgt_paths,&successes,&failures);
|
||||
for(auto const &path : successes)
|
||||
for(const auto &path : successes)
|
||||
{
|
||||
tgt_paths.erase(path);
|
||||
syslog_info("%s is mounted",path.string().c_str());
|
||||
}
|
||||
|
||||
if(first_loop)
|
||||
{
|
||||
for(const auto &path : failures)
|
||||
syslog_notice("%s is not mounted, waiting",path.string().c_str());
|
||||
first_loop = false;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(SLEEP_DURATION);
|
||||
now = std::chrono::steady_clock::now();
|
||||
}
|
||||
@ -124,7 +163,7 @@ fs::wait_for_mount(const fs::Path &src_path_,
|
||||
const std::chrono::milliseconds &timeout_)
|
||||
{
|
||||
int rv;
|
||||
struct stat src_st;
|
||||
struct stat src_st = {0};
|
||||
|
||||
rv = fs::stat(src_path_,&src_st);
|
||||
if(rv == -1)
|
||||
|
@ -173,8 +173,9 @@ namespace l
|
||||
|
||||
paths = cfg_->branches->to_paths();
|
||||
|
||||
syslog_info("Waiting %u seconds for branches to mount",
|
||||
(uint64_t)cfg_->branches_mount_timeout);
|
||||
syslog_info("Waiting %u seconds for %zu branches to mount",
|
||||
(uint64_t)cfg_->branches_mount_timeout,
|
||||
paths.size());
|
||||
|
||||
timeout = std::chrono::milliseconds(cfg_->branches_mount_timeout * 1000);
|
||||
fs::wait_for_mount((std::string)cfg_->mountpoint,
|
||||
|
Loading…
x
Reference in New Issue
Block a user