mirror of https://github.com/trapexit/mergerfs.git
Browse Source
add link_cow feature
add link_cow feature
When enabled if a regular file is opened which has a link count > 1 it will copy the file to a temporary file and rename over the original. Effectively breaking the link. This behavior is similar to cow-shell and other LD_PRELOAD based "CoW" solutions.pull/509/head
Antonio SJ Musumeci
6 years ago
18 changed files with 424 additions and 127 deletions
-
7README.md
-
19man/mergerfs.1
-
1src/config.cpp
-
13src/config.hpp
-
37src/fs_base_open.hpp
-
15src/fs_base_rename.hpp
-
12src/fs_base_unlink.hpp
-
115src/fs_clonefile.cpp
-
9src/fs_clonefile.hpp
-
118src/fs_cow.cpp
-
33src/fs_cow.hpp
-
71src/fs_mktemp.cpp
-
28src/fs_mktemp.hpp
-
2src/getxattr.cpp
-
3src/listxattr.cpp
-
57src/open.cpp
-
5src/option_parser.cpp
-
6src/setxattr.cpp
@ -0,0 +1,118 @@ |
|||||
|
/*
|
||||
|
ISC License |
||||
|
|
||||
|
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
||||
|
|
||||
|
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 "fs_clonefile.hpp"
|
||||
|
#include "fs_mktemp.hpp"
|
||||
|
|
||||
|
#include "fs_base_close.hpp"
|
||||
|
#include "fs_base_open.hpp"
|
||||
|
#include "fs_base_rename.hpp"
|
||||
|
#include "fs_base_stat.hpp"
|
||||
|
#include "fs_base_unlink.hpp"
|
||||
|
|
||||
|
#include <errno.h>
|
||||
|
#include <fcntl.h>
|
||||
|
#include <sys/stat.h>
|
||||
|
#include <sys/types.h>
|
||||
|
#include <unistd.h>
|
||||
|
|
||||
|
#include <string>
|
||||
|
|
||||
|
using std::string; |
||||
|
|
||||
|
static |
||||
|
int |
||||
|
cleanup_on_error(const int src_fd_, |
||||
|
const int dst_fd_ = -1, |
||||
|
const string &dst_fullpath_ = string()) |
||||
|
{ |
||||
|
int error = errno; |
||||
|
|
||||
|
if(src_fd_ >= 0) |
||||
|
fs::close(src_fd_); |
||||
|
if(dst_fd_ >= 0) |
||||
|
fs::close(dst_fd_); |
||||
|
if(!dst_fullpath_.empty()) |
||||
|
fs::unlink(dst_fullpath_); |
||||
|
|
||||
|
errno = error; |
||||
|
|
||||
|
return -1; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
namespace cow |
||||
|
{ |
||||
|
bool |
||||
|
is_eligible(const int flags_, |
||||
|
const struct stat &st_) |
||||
|
{ |
||||
|
return (((flags_ & O_RDWR) || (flags_ & O_WRONLY)) && |
||||
|
(S_ISREG(st_.st_mode)) && |
||||
|
(st_.st_nlink > 1)); |
||||
|
} |
||||
|
|
||||
|
bool |
||||
|
is_eligible(const char *fullpath_, |
||||
|
const int flags_) |
||||
|
{ |
||||
|
int rv; |
||||
|
struct stat st; |
||||
|
|
||||
|
rv = fs::stat(fullpath_,st); |
||||
|
if(rv == -1) |
||||
|
return false; |
||||
|
|
||||
|
return fs::cow::is_eligible(flags_,st); |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
break_link(const char *src_fullpath_) |
||||
|
{ |
||||
|
int rv; |
||||
|
int src_fd; |
||||
|
int dst_fd; |
||||
|
string dst_fullpath; |
||||
|
|
||||
|
src_fd = fs::open(src_fullpath_,O_RDONLY|O_NOFOLLOW|O_LARGEFILE); |
||||
|
if(src_fd == -1) |
||||
|
return -1; |
||||
|
|
||||
|
dst_fullpath = src_fullpath_; |
||||
|
|
||||
|
dst_fd = fs::mktemp(dst_fullpath,O_WRONLY|O_LARGEFILE); |
||||
|
if(dst_fd == -1) |
||||
|
return cleanup_on_error(src_fd); |
||||
|
|
||||
|
rv = fs::clonefile(src_fd,dst_fd); |
||||
|
if(rv == -1) |
||||
|
return cleanup_on_error(src_fd,dst_fd,dst_fullpath); |
||||
|
|
||||
|
rv = fs::rename(dst_fullpath,src_fullpath_); |
||||
|
if(rv == -1) |
||||
|
return cleanup_on_error(src_fd,dst_fd,dst_fullpath); |
||||
|
|
||||
|
fs::close(src_fd); |
||||
|
fs::close(dst_fd); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,33 @@ |
|||||
|
/*
|
||||
|
ISC License |
||||
|
|
||||
|
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
||||
|
|
||||
|
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 <sys/stat.h>
|
||||
|
#include <sys/types.h>
|
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
namespace cow |
||||
|
{ |
||||
|
bool is_eligible(const int flags_, const struct stat &st_); |
||||
|
bool is_eligible(const char *fullpath_, const int flags_); |
||||
|
|
||||
|
int break_link(const char *fullpath_); |
||||
|
} |
||||
|
} |
@ -0,0 +1,71 @@ |
|||||
|
/*
|
||||
|
ISC License |
||||
|
|
||||
|
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
||||
|
|
||||
|
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 "fs_base_open.hpp"
|
||||
|
|
||||
|
#include <fcntl.h>
|
||||
|
#include <string.h>
|
||||
|
|
||||
|
#include <cstdlib>
|
||||
|
|
||||
|
using std::string; |
||||
|
|
||||
|
static |
||||
|
string |
||||
|
generate_tmp_path(const string &base_) |
||||
|
{ |
||||
|
string tmp; |
||||
|
|
||||
|
tmp = base_; |
||||
|
tmp += '_'; |
||||
|
for(int i = 0; i < 6; i++) |
||||
|
tmp += ('A' + (std::rand() % 26)); |
||||
|
|
||||
|
return tmp; |
||||
|
} |
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
int |
||||
|
mktemp(string &base_, |
||||
|
const int flags_) |
||||
|
{ |
||||
|
int fd; |
||||
|
int count; |
||||
|
int flags; |
||||
|
string tmppath; |
||||
|
|
||||
|
fd = -1; |
||||
|
count = 10; |
||||
|
flags = (flags_ | O_EXCL | O_CREAT); |
||||
|
while(count-- > 0) |
||||
|
{ |
||||
|
tmppath = generate_tmp_path(base_); |
||||
|
|
||||
|
fd = fs::open(tmppath,flags,S_IWUSR); |
||||
|
if((fd == -1) && (errno == EEXIST)) |
||||
|
continue; |
||||
|
else if(fd != -1) |
||||
|
base_ = tmppath; |
||||
|
|
||||
|
return fd; |
||||
|
} |
||||
|
|
||||
|
return (errno=EEXIST,-1); |
||||
|
} |
||||
|
} |
@ -0,0 +1,28 @@ |
|||||
|
/*
|
||||
|
ISC License |
||||
|
|
||||
|
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
||||
|
|
||||
|
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 <string>
|
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
int |
||||
|
mktemp(std::string &base_, |
||||
|
const int flags_); |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue