mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-19 16:16:48 +00:00
Refactor fs_inode
* add Algo enum * ReaddirCalc class * string_view params * fs::path overloads
This commit is contained in:
committed by
trapexit
parent
cdadda5eb9
commit
e3a467de80
+270
-88
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user