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