mirror of https://github.com/trapexit/mergerfs.git
5 changed files with 1 additions and 317 deletions
-
4mkdocs/docs/config/functions_categories_policies.md
-
4src/policies.cpp
-
4src/policies.hpp
-
236src/policy_eplup.cpp
-
70src/policy_eplup.hpp
@ -1,236 +0,0 @@ |
|||
/*
|
|||
Copyright (c) 2025, François-Xavier Payet <fx@payet.io> |
|||
|
|||
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_eplup.hpp"
|
|||
|
|||
#include "errno.hpp"
|
|||
#include "fs_exists.hpp"
|
|||
#include "fs_info.hpp"
|
|||
#include "fs_path.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 |
|||
_create(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; /* avoid div-by-zero */ |
|||
|
|||
for (auto &branch : *branches_) |
|||
{ |
|||
if (branch.ro_or_nc()) |
|||
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); |
|||
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_.emplace_back(obranch); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
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_.emplace_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_.emplace_back(obranch); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
int Policy::EPLUP::Action::operator()(const Branches::Ptr &branches_, |
|||
const fs::path &fusepath_, |
|||
std::vector<Branch *> &paths_) const |
|||
{ |
|||
return ::_action(branches_, fusepath_, paths_); |
|||
} |
|||
|
|||
int Policy::EPLUP::Create::operator()(const Branches::Ptr &branches_, |
|||
const fs::path &fusepath_, |
|||
std::vector<Branch *> &paths_) const |
|||
{ |
|||
return ::_create(branches_, fusepath_, paths_); |
|||
} |
|||
|
|||
int Policy::EPLUP::Search::operator()(const Branches::Ptr &branches_, |
|||
const fs::path &fusepath_, |
|||
std::vector<Branch *> &paths_) const |
|||
{ |
|||
return ::_search(branches_, fusepath_, paths_); |
|||
} |
|||
@ -1,70 +0,0 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2025, François-Xavier Payet <fx@payet.io> |
|||
|
|||
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 EPLUP |
|||
{ |
|||
class Action final : public Policy::ActionImpl |
|||
{ |
|||
public: |
|||
Action() |
|||
: Policy::ActionImpl("eplup") |
|||
{ |
|||
} |
|||
|
|||
public: |
|||
int operator()(const Branches::Ptr &, |
|||
const fs::path &, |
|||
std::vector<Branch *> &) const final; |
|||
}; |
|||
|
|||
class Create final : public Policy::CreateImpl |
|||
{ |
|||
public: |
|||
Create() |
|||
: Policy::CreateImpl("eplup") |
|||
{ |
|||
} |
|||
|
|||
public: |
|||
int operator()(const Branches::Ptr &, |
|||
const fs::path &, |
|||
std::vector<Branch *> &) const final; |
|||
bool path_preserving(void) const final { return true; } |
|||
}; |
|||
|
|||
class Search final : public Policy::SearchImpl |
|||
{ |
|||
public: |
|||
Search() |
|||
: Policy::SearchImpl("eplup") |
|||
{ |
|||
} |
|||
|
|||
public: |
|||
int operator()(const Branches::Ptr &, |
|||
const fs::path &, |
|||
std::vector<Branch *> &) const final; |
|||
}; |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue