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