mirror of https://github.com/trapexit/mergerfs.git
3 changed files with 125 additions and 1 deletions
@ -0,0 +1,119 @@ |
|||||
|
/*
|
||||
|
Copyright (c) 2020, LiveIntent ApS, Andreas E. Dalsgaard <andreas.dalsgaard@gmail.com> |
||||
|
|
||||
|
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 "errno.hpp"
|
||||
|
#include "fs.hpp"
|
||||
|
#include "fs_exists.hpp"
|
||||
|
#include "fs_info.hpp"
|
||||
|
#include "fs_path.hpp"
|
||||
|
#include "policy.hpp"
|
||||
|
#include "policy_error.hpp"
|
||||
|
#include "rwlock.hpp"
|
||||
|
|
||||
|
#include <string>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
using std::string; |
||||
|
using std::vector; |
||||
|
|
||||
|
namespace fair |
||||
|
{ |
||||
|
uint64_t get_int64_rand(uint64_t const& min, uint64_t const& max) |
||||
|
{ |
||||
|
return (((uint64_t)(unsigned int)rand() << 32) + (uint64_t)(unsigned int)rand()) % (max - min) + min; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
int |
||||
|
create(const Branches &branches_, |
||||
|
const uint64_t minfreespace_, |
||||
|
vector<string> *paths_) |
||||
|
{ |
||||
|
rwlock::ReadGuard guard(&branches_.lock); |
||||
|
|
||||
|
int rv; |
||||
|
int error; |
||||
|
uint64_t sum, index; |
||||
|
uint64_t random_byte; |
||||
|
fs::info_t info; |
||||
|
const Branch *branch; |
||||
|
const string *fairbasepath; |
||||
|
|
||||
|
error = ENOENT; |
||||
|
fairbasepath = NULL; |
||||
|
sum = 0, index = 0; |
||||
|
for(size_t i = 0, ei = branches_.size(); i != ei; i++) |
||||
|
{ |
||||
|
branch = &branches_[i]; |
||||
|
|
||||
|
if(branch->ro_or_nc()) |
||||
|
error_and_continue(error,EROFS); |
||||
|
rv = fs::info(&branch->path,&info); |
||||
|
if(rv == -1) |
||||
|
error_and_continue(error,ENOENT); |
||||
|
if(info.readonly) |
||||
|
error_and_continue(error,EROFS); |
||||
|
if(info.spaceavail < minfreespace_) |
||||
|
error_and_continue(error,ENOSPC); |
||||
|
|
||||
|
sum += info.spaceavail; |
||||
|
} |
||||
|
|
||||
|
random_byte = get_int64_rand(0, sum); |
||||
|
|
||||
|
for(size_t i = 0, ei = branches_.size(); i != ei; i++) |
||||
|
{ |
||||
|
branch = &branches_[i]; |
||||
|
|
||||
|
if(branch->ro_or_nc()) |
||||
|
error_and_continue(error,EROFS); |
||||
|
rv = fs::info(&branch->path,&info); |
||||
|
if(rv == -1) |
||||
|
error_and_continue(error,ENOENT); |
||||
|
if(info.readonly) |
||||
|
error_and_continue(error,EROFS); |
||||
|
if(info.spaceavail < minfreespace_) |
||||
|
error_and_continue(error,ENOSPC); |
||||
|
|
||||
|
index += info.spaceavail; |
||||
|
|
||||
|
if(index > random_byte) { |
||||
|
fairbasepath = &branch->path; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if(fairbasepath == NULL) |
||||
|
return (errno=error,-1); |
||||
|
|
||||
|
paths_->push_back(*fairbasepath); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Policy::Func::fair(const Category::Enum::Type type, |
||||
|
const Branches &branches_, |
||||
|
const char *fusepath, |
||||
|
const uint64_t minfreespace, |
||||
|
vector<string> *paths) |
||||
|
{ |
||||
|
if(type == Category::Enum::create) |
||||
|
return fair::create(branches_,minfreespace,paths); |
||||
|
|
||||
|
return Policy::Func::epmfs(type,branches_,fusepath,minfreespace,paths); |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue