Browse Source

Add LUP/EPLUP policies

pull/1600/head
François-Xavier Payet 5 days ago
parent
commit
e7f43fd352
  1. 8
      src/policies.hpp
  2. 236
      src/policy_eplup.cpp
  3. 70
      src/policy_eplup.hpp
  4. 112
      src/policy_lup.cpp
  5. 70
      src/policy_lup.hpp

8
src/policies.hpp

@ -23,6 +23,7 @@
#include "policy_epff.hpp" #include "policy_epff.hpp"
#include "policy_eplfs.hpp" #include "policy_eplfs.hpp"
#include "policy_eplus.hpp" #include "policy_eplus.hpp"
#include "policy_eplup.hpp"
#include "policy_epmfs.hpp" #include "policy_epmfs.hpp"
#include "policy_eppfrd.hpp" #include "policy_eppfrd.hpp"
#include "policy_eprand.hpp" #include "policy_eprand.hpp"
@ -30,6 +31,7 @@
#include "policy_ff.hpp" #include "policy_ff.hpp"
#include "policy_lfs.hpp" #include "policy_lfs.hpp"
#include "policy_lus.hpp" #include "policy_lus.hpp"
#include "policy_lup.hpp"
#include "policy_mfs.hpp" #include "policy_mfs.hpp"
#include "policy_msplfs.hpp" #include "policy_msplfs.hpp"
#include "policy_msplus.hpp" #include "policy_msplus.hpp"
@ -49,6 +51,7 @@ struct Policies
static Policy::EPAll::Action epall; static Policy::EPAll::Action epall;
static Policy::EPFF::Action epff; static Policy::EPFF::Action epff;
static Policy::EPLFS::Action eplfs; static Policy::EPLFS::Action eplfs;
static Policy::EPLUP::Action eplup;
static Policy::EPLUS::Action eplus; static Policy::EPLUS::Action eplus;
static Policy::EPMFS::Action epmfs; static Policy::EPMFS::Action epmfs;
static Policy::EPPFRD::Action eppfrd; static Policy::EPPFRD::Action eppfrd;
@ -56,6 +59,7 @@ struct Policies
static Policy::ERoFS::Action erofs; static Policy::ERoFS::Action erofs;
static Policy::FF::Action ff; static Policy::FF::Action ff;
static Policy::LFS::Action lfs; static Policy::LFS::Action lfs;
static Policy::LUP::Action lup;
static Policy::LUS::Action lus; static Policy::LUS::Action lus;
static Policy::MFS::Action mfs; static Policy::MFS::Action mfs;
static Policy::MSPLFS::Action msplfs; static Policy::MSPLFS::Action msplfs;
@ -75,6 +79,7 @@ struct Policies
static Policy::EPAll::Create epall; static Policy::EPAll::Create epall;
static Policy::EPFF::Create epff; static Policy::EPFF::Create epff;
static Policy::EPLFS::Create eplfs; static Policy::EPLFS::Create eplfs;
static Policy::EPLUP::Create eplup;
static Policy::EPLUS::Create eplus; static Policy::EPLUS::Create eplus;
static Policy::EPMFS::Create epmfs; static Policy::EPMFS::Create epmfs;
static Policy::EPPFRD::Create eppfrd; static Policy::EPPFRD::Create eppfrd;
@ -82,6 +87,7 @@ struct Policies
static Policy::ERoFS::Create erofs; static Policy::ERoFS::Create erofs;
static Policy::FF::Create ff; static Policy::FF::Create ff;
static Policy::LFS::Create lfs; static Policy::LFS::Create lfs;
static Policy::LUP::Create lup;
static Policy::LUS::Create lus; static Policy::LUS::Create lus;
static Policy::MFS::Create mfs; static Policy::MFS::Create mfs;
static Policy::MSPLFS::Create msplfs; static Policy::MSPLFS::Create msplfs;
@ -101,6 +107,7 @@ struct Policies
static Policy::EPAll::Search epall; static Policy::EPAll::Search epall;
static Policy::EPFF::Search epff; static Policy::EPFF::Search epff;
static Policy::EPLFS::Search eplfs; static Policy::EPLFS::Search eplfs;
static Policy::EPLUP::Search eplup;
static Policy::EPLUS::Search eplus; static Policy::EPLUS::Search eplus;
static Policy::EPMFS::Search epmfs; static Policy::EPMFS::Search epmfs;
static Policy::EPPFRD::Search eppfrd; static Policy::EPPFRD::Search eppfrd;
@ -108,6 +115,7 @@ struct Policies
static Policy::ERoFS::Search erofs; static Policy::ERoFS::Search erofs;
static Policy::FF::Search ff; static Policy::FF::Search ff;
static Policy::LFS::Search lfs; static Policy::LFS::Search lfs;
static Policy::LUP::Search lup;
static Policy::LUS::Search lus; static Policy::LUS::Search lus;
static Policy::MFS::Search mfs; static Policy::MFS::Search mfs;
static Policy::MSPLFS::Search msplfs; static Policy::MSPLFS::Search msplfs;

236
src/policy_eplup.cpp

@ -0,0 +1,236 @@
/*
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_);
}

70
src/policy_eplup.hpp

@ -0,0 +1,70 @@
/*
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;
};
}
}

112
src/policy_lup.cpp

@ -0,0 +1,112 @@
/*
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_lup.hpp"
#include "errno.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_,
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 Policies::Action::eplup(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 Policies::Search::eplup(branches_, fusepath_, paths_);
}

70
src/policy_lup.hpp

@ -0,0 +1,70 @@
/*
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 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…
Cancel
Save