Refactor fs_inode

* add Algo enum
* ReaddirCalc class
* string_view params
* fs::path overloads
This commit is contained in:
Antonio S. Musumeci
2026-04-12 23:44:23 -05:00
committed by trapexit
parent cdadda5eb9
commit e3a467de80
2 changed files with 313 additions and 88 deletions
+270 -88
View File
@@ -18,20 +18,18 @@
#include "fs_inode.hpp"
#include "ef.hpp"
#include "rapidhash/rapidhash.h"
#include <atomic>
#include <pthread.h>
#include <sys/stat.h>
typedef u64 (*inodefunc_t)(const std::string &,
const std::string &,
typedef u64 (*inodefunc_t)(const std::string_view,
const std::string_view,
const mode_t,
const ino_t);
static u64 _hybrid_hash(const std::string &,
const std::string &,
static u64 _hybrid_hash(const std::string_view,
const std::string_view,
const mode_t,
const ino_t);
@@ -39,6 +37,13 @@ static u64 _hybrid_hash(const std::string &,
static std::atomic<inodefunc_t> g_func{::_hybrid_hash};
static
const void*
_data(const std::string_view s_)
{
return (s_.empty() ? "" : s_.data());
}
static
u32
_h64_to_h32(u64 h_)
@@ -50,83 +55,116 @@ _h64_to_h32(u64 h_)
static
u64
_passthrough(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_hash(const std::string_view s_)
{
return rapidhash(::_data(s_),
s_.size());
}
static
u64
_branch_seed(const std::string_view branch_path_)
{
return ::_hash(branch_path_);
}
static
u64
_devino_hash_from_seed(const u64 branch_seed_,
const ino_t ino_)
{
return rapidhash_withSeed(&ino_,
sizeof(ino_),
branch_seed_);
}
static
u64
_path_hash_value(const std::string_view fusepath_)
{
return ::_hash(fusepath_);
}
static
u64
_path_hash32_value(const std::string_view fusepath_)
{
return ::_h64_to_h32(::_path_hash_value(fusepath_));
}
static
u64
_devino_hash_value(const std::string_view branch_path_,
const ino_t ino_)
{
return ::_devino_hash_from_seed(::_branch_seed(branch_path_),
ino_);
}
static
u64
_devino_hash32_value(const std::string_view branch_path_,
const ino_t ino_)
{
return ::_h64_to_h32(::_devino_hash_value(branch_path_,ino_));
}
static
u64
_passthrough(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
return ino_;
}
static
u64
_path_hash(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_path_hash(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
u64 seed;
seed = rapidhash(&fusepath_[0],fusepath_.size());
return seed;
return ::_path_hash_value(fusepath_);
}
static
u64
_path_hash32(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_path_hash32(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
u64 h;
h = ::_path_hash(branch_path_,
fusepath_,
mode_,
ino_);
return ::_h64_to_h32(h);
return ::_path_hash32_value(fusepath_);
}
static
u64
_devino_hash(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_devino_hash(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
u64 seed;
seed = rapidhash(&branch_path_[0],branch_path_.size());
seed = rapidhash_withSeed(&ino_,sizeof(ino_),seed);
return seed;
return ::_devino_hash_value(branch_path_,ino_);
}
static
u64
_devino_hash32(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_devino_hash32(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
u64 h;
h = ::_devino_hash(branch_path_,
fusepath_,
mode_,
ino_);
return ::_h64_to_h32(h);
return ::_devino_hash32_value(branch_path_,ino_);
}
static
u64
_hybrid_hash(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
_hybrid_hash(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
return (S_ISDIR(mode_) ?
::_path_hash(branch_path_,fusepath_,mode_,ino_) :
@@ -135,8 +173,8 @@ _hybrid_hash(const std::string &branch_path_,
static
u64
_hybrid_hash32(const std::string &branch_path_,
const std::string &fusepath_,
_hybrid_hash32(const std::string_view branch_path_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
@@ -145,58 +183,180 @@ _hybrid_hash32(const std::string &branch_path_,
::_devino_hash32(branch_path_,fusepath_,mode_,ino_));
}
static
fs::inode::Algo
_algo_from_func(const inodefunc_t func_)
{
if(func_ == ::_passthrough)
return fs::inode::Algo::PASSTHROUGH;
if(func_ == ::_path_hash)
return fs::inode::Algo::PATH_HASH;
if(func_ == ::_path_hash32)
return fs::inode::Algo::PATH_HASH32;
if(func_ == ::_devino_hash)
return fs::inode::Algo::DEVINO_HASH;
if(func_ == ::_devino_hash32)
return fs::inode::Algo::DEVINO_HASH32;
if(func_ == ::_hybrid_hash)
return fs::inode::Algo::HYBRID_HASH;
if(func_ == ::_hybrid_hash32)
return fs::inode::Algo::HYBRID_HASH32;
return fs::inode::Algo::HYBRID_HASH;
}
static
u64
_calc_with_algo(const fs::inode::Algo algo_,
const u64 branch_seed_,
const std::string_view fusepath_,
const mode_t mode_,
const ino_t ino_)
{
switch(algo_)
{
case fs::inode::Algo::PASSTHROUGH:
return ino_;
case fs::inode::Algo::PATH_HASH:
return ::_path_hash_value(fusepath_);
case fs::inode::Algo::PATH_HASH32:
return ::_path_hash32_value(fusepath_);
case fs::inode::Algo::DEVINO_HASH:
return ::_devino_hash_from_seed(branch_seed_,ino_);
case fs::inode::Algo::DEVINO_HASH32:
return ::_h64_to_h32(::_devino_hash_from_seed(branch_seed_,ino_));
case fs::inode::Algo::HYBRID_HASH:
return (S_ISDIR(mode_) ?
::_path_hash_value(fusepath_) :
::_devino_hash_from_seed(branch_seed_,ino_));
case fs::inode::Algo::HYBRID_HASH32:
return (S_ISDIR(mode_) ?
::_path_hash32_value(fusepath_) :
::_h64_to_h32(::_devino_hash_from_seed(branch_seed_,ino_)));
}
return ino_;
}
int
fs::inode::set_algo(const std::string &algo_)
{
inodefunc_t func = nullptr;
if(algo_ == "passthrough")
g_func.store(::_passthrough);
ef(algo_ == "path-hash")
g_func.store(::_path_hash);
ef(algo_ == "path-hash32")
g_func.store(::_path_hash32);
ef(algo_ == "devino-hash")
g_func.store(::_devino_hash);
ef(algo_ == "devino-hash32")
g_func.store(::_devino_hash32);
ef(algo_ == "hybrid-hash")
g_func.store(::_hybrid_hash);
ef(algo_ == "hybrid-hash32")
g_func.store(::_hybrid_hash32);
func = ::_passthrough;
else if(algo_ == "path-hash")
func = ::_path_hash;
else if(algo_ == "path-hash32")
func = ::_path_hash32;
else if(algo_ == "devino-hash")
func = ::_devino_hash;
else if(algo_ == "devino-hash32")
func = ::_devino_hash32;
else if(algo_ == "hybrid-hash")
func = ::_hybrid_hash;
else if(algo_ == "hybrid-hash32")
func = ::_hybrid_hash32;
else
return -EINVAL;
g_func.store(func);
return 0;
}
std::string
fs::inode::get_algo(void)
{
inodefunc_t func = g_func.load();
if(func == ::_passthrough)
return "passthrough";
if(func == ::_path_hash)
return "path-hash";
if(func == ::_path_hash32)
return "path-hash32";
if(func == ::_devino_hash)
return "devino-hash";
if(func == ::_devino_hash32)
return "devino-hash32";
if(func == ::_hybrid_hash)
return "hybrid-hash";
if(func == ::_hybrid_hash32)
return "hybrid-hash32";
switch(::_algo_from_func(g_func.load()))
{
case fs::inode::Algo::PASSTHROUGH:
return "passthrough";
case fs::inode::Algo::PATH_HASH:
return "path-hash";
case fs::inode::Algo::PATH_HASH32:
return "path-hash32";
case fs::inode::Algo::DEVINO_HASH:
return "devino-hash";
case fs::inode::Algo::DEVINO_HASH32:
return "devino-hash32";
case fs::inode::Algo::HYBRID_HASH:
return "hybrid-hash";
case fs::inode::Algo::HYBRID_HASH32:
return "hybrid-hash32";
}
return {};
}
fs::inode::ReaddirCalc::ReaddirCalc(const fs::path &branch_path_,
const fs::path &dirpath_)
: _algo(::_algo_from_func(g_func.load())),
_branch_seed(::_branch_seed(branch_path_.native())),
_fusepath((dirpath_ / "__mergerfs__").native()),
_filename_offset(_fusepath.size() - std::string_view("__mergerfs__").size())
{
}
u64
fs::inode::ReaddirCalc::calc(const char *name_,
const std::size_t namelen_,
const mode_t mode_,
const ino_t ino_)
{
switch(_algo)
{
case Algo::PASSTHROUGH:
return ino_;
case Algo::DEVINO_HASH:
return ::_devino_hash_from_seed(_branch_seed,ino_);
case Algo::DEVINO_HASH32:
return ::_h64_to_h32(::_devino_hash_from_seed(_branch_seed,ino_));
case Algo::HYBRID_HASH:
if(!S_ISDIR(mode_))
return ::_devino_hash_from_seed(_branch_seed,ino_);
break;
case Algo::HYBRID_HASH32:
if(!S_ISDIR(mode_))
return ::_h64_to_h32(::_devino_hash_from_seed(_branch_seed,ino_));
break;
case Algo::PATH_HASH:
case Algo::PATH_HASH32:
break;
}
_fusepath.resize(_filename_offset);
_fusepath.append(name_,namelen_);
return ::_calc_with_algo(_algo,
_branch_seed,
_fusepath,
mode_,
ino_);
}
u64
fs::inode::calc(const std::string &branch_path_,
const std::string &fusepath_,
const mode_t mode_,
const ino_t ino_)
{
return g_func.load()(branch_path_,fusepath_,mode_,ino_);
return g_func.load()(branch_path_,
fusepath_,
mode_,
ino_);
}
u64
fs::inode::calc(const fs::path &branch_path_,
const fs::path &fusepath_,
const mode_t mode_,
const ino_t ino_)
{
return g_func.load()(branch_path_.native(),
fusepath_.native(),
mode_,
ino_);
}
void
@@ -210,6 +370,17 @@ fs::inode::calc(const std::string &branch_path_,
st_->st_ino);
}
void
fs::inode::calc(const fs::path &branch_path_,
const fs::path &fusepath_,
struct stat *st_)
{
st_->st_ino = calc(branch_path_,
fusepath_,
st_->st_mode,
st_->st_ino);
}
void
fs::inode::calc(const std::string &branch_path_,
const std::string &fusepath_,
@@ -220,3 +391,14 @@ fs::inode::calc(const std::string &branch_path_,
st_->mode,
st_->ino);
}
void
fs::inode::calc(const fs::path &branch_path_,
const fs::path &fusepath_,
struct fuse_statx *st_)
{
st_->ino = calc(branch_path_,
fusepath_,
st_->mode,
st_->ino);
}
+43
View File
@@ -19,9 +19,12 @@
#pragma once
#include "base_types.h"
#include "fs_path.hpp"
#include "fuse_kernel.h"
#include <cstddef>
#include <string>
#include <string_view>
#include <sys/stat.h>
@@ -30,6 +33,36 @@ namespace fs
{
namespace inode
{
enum class Algo
{
PASSTHROUGH,
PATH_HASH,
PATH_HASH32,
DEVINO_HASH,
DEVINO_HASH32,
HYBRID_HASH,
HYBRID_HASH32,
};
class ReaddirCalc
{
public:
ReaddirCalc(const fs::path &branch_path,
const fs::path &dirpath);
public:
u64 calc(const char *name,
const size_t namelen,
const mode_t mode,
const ino_t ino);
private:
Algo _algo;
u64 _branch_seed;
std::string _fusepath;
std::size_t _filename_offset;
};
int set_algo(const std::string &s);
std::string get_algo(void);
@@ -37,12 +70,22 @@ namespace fs
const std::string &fusepath,
const mode_t mode,
const ino_t ino);
u64 calc(const fs::path &basepath,
const fs::path &fusepath,
const mode_t mode,
const ino_t ino);
void calc(const std::string &basepath,
const std::string &fusepath,
struct stat *st);
void calc(const fs::path &basepath,
const fs::path &fusepath,
struct stat *st);
void calc(const std::string &basepath,
const std::string &fusepath,
struct fuse_statx *st);
void calc(const fs::path &basepath,
const fs::path &fusepath,
struct fuse_statx *st);
}
}