mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-25 18:40:18 -04:00
This commit is contained in:
parent
72fb6e4aba
commit
22df87c86a
5 changed files with 316 additions and 0 deletions
|
|
@ -116,6 +116,7 @@ but it makes things a bit more uniform.
|
|||
| mfs (most free space) | Pick the branch with the most available free space. |
|
||||
| ff (first found) | Given the order of the branches, as defined at mount time or configured at runtime, act on the first one found. |
|
||||
| lfs (least free space) | Pick the branch with the least available free space. |
|
||||
| lup (least used percent) | Pick the branch with the least used percentage of space |
|
||||
| lus (least used space) | Pick the branch with the least used space. |
|
||||
| all | Search: For **mkdir**, **mknod**, and **symlink** it will apply to all branches. **create** works like **ff**. |
|
||||
| msppfrd (most shared path, percentage free random distribution) | Like **eppfrd** but if it fails to find a branch it will try again with the parent directory. Continues this pattern till finding one. |
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
FUNC(ff) \
|
||||
FUNC(lfs) \
|
||||
FUNC(lus) \
|
||||
FUNC(lup) \
|
||||
FUNC(mfs) \
|
||||
FUNC(msplfs) \
|
||||
FUNC(msplus) \
|
||||
|
|
@ -80,6 +81,7 @@ Policy::ERoFS::Action Policies::Action::erofs;
|
|||
Policy::FF::Action Policies::Action::ff;
|
||||
Policy::LFS::Action Policies::Action::lfs;
|
||||
Policy::LUS::Action Policies::Action::lus;
|
||||
Policy::LUP::Action Policies::Action::lup;
|
||||
Policy::MFS::Action Policies::Action::mfs;
|
||||
Policy::MSPLFS::Action Policies::Action::msplfs;
|
||||
Policy::MSPLUS::Action Policies::Action::msplus;
|
||||
|
|
@ -101,6 +103,7 @@ Policy::ERoFS::Create Policies::Create::erofs;
|
|||
Policy::FF::Create Policies::Create::ff;
|
||||
Policy::LFS::Create Policies::Create::lfs;
|
||||
Policy::LUS::Create Policies::Create::lus;
|
||||
Policy::LUP::Create Policies::Create::lup;
|
||||
Policy::MFS::Create Policies::Create::mfs;
|
||||
Policy::MSPLFS::Create Policies::Create::msplfs;
|
||||
Policy::MSPLUS::Create Policies::Create::msplus;
|
||||
|
|
@ -122,6 +125,7 @@ Policy::ERoFS::Search Policies::Search::erofs;
|
|||
Policy::FF::Search Policies::Search::ff;
|
||||
Policy::LFS::Search Policies::Search::lfs;
|
||||
Policy::LUS::Search Policies::Search::lus;
|
||||
Policy::LUP::Search Policies::Search::lup;
|
||||
Policy::MFS::Search Policies::Search::mfs;
|
||||
Policy::MSPLFS::Search Policies::Search::msplfs;
|
||||
Policy::MSPLUS::Search Policies::Search::msplus;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "policy_ff.hpp"
|
||||
#include "policy_lfs.hpp"
|
||||
#include "policy_lus.hpp"
|
||||
#include "policy_lup.hpp"
|
||||
#include "policy_mfs.hpp"
|
||||
#include "policy_msplfs.hpp"
|
||||
#include "policy_msplus.hpp"
|
||||
|
|
@ -56,6 +57,7 @@ struct Policies
|
|||
static Policy::ERoFS::Action erofs;
|
||||
static Policy::FF::Action ff;
|
||||
static Policy::LFS::Action lfs;
|
||||
static Policy::LUP::Action lup;
|
||||
static Policy::LUS::Action lus;
|
||||
static Policy::MFS::Action mfs;
|
||||
static Policy::MSPLFS::Action msplfs;
|
||||
|
|
@ -82,6 +84,7 @@ struct Policies
|
|||
static Policy::ERoFS::Create erofs;
|
||||
static Policy::FF::Create ff;
|
||||
static Policy::LFS::Create lfs;
|
||||
static Policy::LUP::Create lup;
|
||||
static Policy::LUS::Create lus;
|
||||
static Policy::MFS::Create mfs;
|
||||
static Policy::MSPLFS::Create msplfs;
|
||||
|
|
@ -108,6 +111,7 @@ struct Policies
|
|||
static Policy::ERoFS::Search erofs;
|
||||
static Policy::FF::Search ff;
|
||||
static Policy::LFS::Search lfs;
|
||||
static Policy::LUP::Search lup;
|
||||
static Policy::LUS::Search lus;
|
||||
static Policy::MFS::Search mfs;
|
||||
static Policy::MSPLFS::Search msplfs;
|
||||
|
|
|
|||
240
src/policy_lup.cpp
Normal file
240
src/policy_lup.cpp
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
Copyright (c) 2025, Antonio SJ Musumeci <trapexit@spawn.link> and contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "policy_lup.hpp"
|
||||
|
||||
#include "errno.hpp"
|
||||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "policies.hpp"
|
||||
#include "fs_statvfs_cache.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "policy_error.hpp"
|
||||
#include "rwlock.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
static
|
||||
int
|
||||
_action(const Branches::Ptr &branches_,
|
||||
const fs::path &fusepath_,
|
||||
std::vector<Branch *> &paths_)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
fs::info_t info;
|
||||
Branch *obranch;
|
||||
|
||||
obranch = nullptr;
|
||||
error = ENOENT;
|
||||
|
||||
uint64_t best_used = 0;
|
||||
uint64_t best_total = 1;
|
||||
|
||||
for (auto &branch : *branches_)
|
||||
{
|
||||
if (branch.ro())
|
||||
error_and_continue(error, EROFS);
|
||||
if (!fs::exists(branch.path, fusepath_))
|
||||
error_and_continue(error, ENOENT);
|
||||
rv = fs::info(branch.path, &info);
|
||||
if (rv < 0)
|
||||
error_and_continue(error, ENOENT);
|
||||
if (info.readonly)
|
||||
error_and_continue(error, EROFS);
|
||||
|
||||
uint64_t used = info.spaceused;
|
||||
uint64_t total = info.spaceused + info.spaceavail;
|
||||
if (total == 0)
|
||||
{
|
||||
used = 0;
|
||||
total = 1;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
{
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned __int128 lhs = (unsigned __int128)used * (unsigned __int128)best_total;
|
||||
unsigned __int128 rhs = (unsigned __int128)best_used * (unsigned __int128)total;
|
||||
if (lhs >= rhs)
|
||||
continue;
|
||||
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
return -error;
|
||||
|
||||
paths_.push_back(obranch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_search(const Branches::Ptr &branches_,
|
||||
const fs::path &fusepath_,
|
||||
std::vector<Branch *> &paths_)
|
||||
{
|
||||
int rv;
|
||||
uint64_t used;
|
||||
uint64_t avail;
|
||||
uint64_t best_used = 0;
|
||||
uint64_t best_total = 1;
|
||||
Branch *obranch;
|
||||
|
||||
obranch = nullptr;
|
||||
|
||||
for (auto &branch : *branches_)
|
||||
{
|
||||
if (!fs::exists(branch.path, fusepath_))
|
||||
continue;
|
||||
rv = fs::statvfs_cache_spaceused(branch.path, &used);
|
||||
if (rv < 0)
|
||||
continue;
|
||||
rv = fs::statvfs_cache_spaceavail(branch.path, &avail);
|
||||
if (rv < 0)
|
||||
continue;
|
||||
|
||||
uint64_t total = used + avail;
|
||||
if (total == 0)
|
||||
{
|
||||
used = 0;
|
||||
total = 1;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
{
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned __int128 lhs = (unsigned __int128)used * (unsigned __int128)best_total;
|
||||
unsigned __int128 rhs = (unsigned __int128)best_used * (unsigned __int128)total;
|
||||
if (lhs >= rhs)
|
||||
continue;
|
||||
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
return -ENOENT;
|
||||
|
||||
paths_.push_back(obranch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_create(const Branches::Ptr &branches_,
|
||||
std::vector<Branch *> &paths_)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
fs::info_t info;
|
||||
Branch *obranch;
|
||||
|
||||
obranch = nullptr;
|
||||
error = ENOENT;
|
||||
|
||||
uint64_t best_used = 0;
|
||||
uint64_t best_total = 1;
|
||||
|
||||
for (auto &branch : *branches_)
|
||||
{
|
||||
if (branch.ro_or_nc())
|
||||
error_and_continue(error, EROFS);
|
||||
rv = fs::info(branch.path, &info);
|
||||
if (rv < 0)
|
||||
error_and_continue(error, ENOENT);
|
||||
if (info.readonly)
|
||||
error_and_continue(error, EROFS);
|
||||
if (info.spaceavail < branch.minfreespace())
|
||||
error_and_continue(error, ENOSPC);
|
||||
|
||||
uint64_t used = info.spaceused;
|
||||
uint64_t total = info.spaceused + info.spaceavail;
|
||||
if (total == 0)
|
||||
{
|
||||
used = 0;
|
||||
total = 1;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
{
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned __int128 lhs = (unsigned __int128)used * (unsigned __int128)best_total;
|
||||
unsigned __int128 rhs = (unsigned __int128)best_used * (unsigned __int128)total;
|
||||
if (lhs >= rhs)
|
||||
continue;
|
||||
|
||||
best_used = used;
|
||||
best_total = total;
|
||||
obranch = &branch;
|
||||
}
|
||||
|
||||
if (obranch == nullptr)
|
||||
return -error;
|
||||
|
||||
paths_.push_back(obranch);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
Policy::LUP::Action::operator()(const Branches::Ptr &branches_,
|
||||
const fs::path &fusepath_,
|
||||
std::vector<Branch *> &paths_) const
|
||||
{
|
||||
return ::_action(branches_, fusepath_, paths_);
|
||||
}
|
||||
|
||||
int
|
||||
Policy::LUP::Create::operator()(const Branches::Ptr &branches_,
|
||||
const fs::path &fusepath_,
|
||||
std::vector<Branch *> &paths_) const
|
||||
{
|
||||
return ::_create(branches_, paths_);
|
||||
}
|
||||
|
||||
int
|
||||
Policy::LUP::Search::operator()(const Branches::Ptr &branches_,
|
||||
const fs::path &fusepath_,
|
||||
std::vector<Branch *> &paths_) const
|
||||
{
|
||||
return ::_search(branches_, fusepath_, paths_);
|
||||
}
|
||||
67
src/policy_lup.hpp
Normal file
67
src/policy_lup.hpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
Copyright (c) 2025, Antonio SJ Musumeci <trapexit@spawn.link> and contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "policy.hpp"
|
||||
|
||||
namespace Policy
|
||||
{
|
||||
namespace LUP
|
||||
{
|
||||
class Action final : public Policy::ActionImpl
|
||||
{
|
||||
public:
|
||||
Action()
|
||||
: Policy::ActionImpl("lup")
|
||||
{}
|
||||
|
||||
public:
|
||||
int operator()(const Branches::Ptr &,
|
||||
const fs::path &,
|
||||
std::vector<Branch *> &) const final;
|
||||
};
|
||||
|
||||
class Create final : public Policy::CreateImpl
|
||||
{
|
||||
public:
|
||||
Create()
|
||||
: Policy::CreateImpl("lup")
|
||||
{}
|
||||
|
||||
public:
|
||||
int operator()(const Branches::Ptr &,
|
||||
const fs::path &,
|
||||
std::vector<Branch *> &) const final;
|
||||
bool path_preserving() const final { return false; }
|
||||
};
|
||||
|
||||
class Search final : public Policy::SearchImpl
|
||||
{
|
||||
public:
|
||||
Search()
|
||||
: Policy::SearchImpl("lup")
|
||||
{}
|
||||
|
||||
public:
|
||||
int operator()(const Branches::Ptr &,
|
||||
const fs::path &,
|
||||
std::vector<Branch *> &) const final;
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue