mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-04-24 22:14:05 +08:00
Fix moveonenospc when file opened with append mode
This commit is contained in:
parent
701f88de43
commit
82430e1079
@ -57,8 +57,7 @@ namespace l
|
||||
int
|
||||
copydata_readwrite(const int src_fd_,
|
||||
const int dst_fd_,
|
||||
const size_t count_,
|
||||
const size_t blocksize_)
|
||||
const size_t count_)
|
||||
{
|
||||
ssize_t nr;
|
||||
ssize_t nw;
|
||||
@ -66,7 +65,7 @@ namespace l
|
||||
size_t totalwritten;
|
||||
vector<char> buf;
|
||||
|
||||
bufsize = (blocksize_ * 16);
|
||||
bufsize = (128 * 1024);
|
||||
buf.resize(bufsize);
|
||||
|
||||
fs::lseek(src_fd_,0,SEEK_SET);
|
||||
@ -108,7 +107,6 @@ namespace fs
|
||||
|
||||
return l::copydata_readwrite(src_fd_,
|
||||
dst_fd_,
|
||||
st.st_size,
|
||||
st.st_blksize);
|
||||
st.st_size);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ namespace fs
|
||||
|
||||
fd = -1;
|
||||
count = MAX_ATTEMPTS;
|
||||
flags = (flags_ | O_EXCL | O_CREAT);
|
||||
flags = (flags_ | O_EXCL | O_CREAT | O_TRUNC);
|
||||
while(count-- > 0)
|
||||
{
|
||||
tmppath = generate_tmp_path(*base_);
|
||||
|
@ -44,6 +44,21 @@ using std::string;
|
||||
using std::vector;
|
||||
|
||||
|
||||
static
|
||||
int
|
||||
cleanup_flags(const int flags_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = flags_;
|
||||
rv = (rv & ~O_TRUNC);
|
||||
rv = (rv & ~O_CREAT);
|
||||
rv = (rv & ~O_EXCL);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
namespace l
|
||||
{
|
||||
static
|
||||
@ -51,82 +66,99 @@ namespace l
|
||||
movefile(const Policy::Create &createFunc_,
|
||||
const Branches::CPtr &branches_,
|
||||
const string &fusepath_,
|
||||
int *origfd_)
|
||||
int origfd_)
|
||||
{
|
||||
int rv;
|
||||
int fdin;
|
||||
int fdout;
|
||||
int fdin_flags;
|
||||
int64_t fdin_size;
|
||||
int srcfd;
|
||||
int dstfd;
|
||||
int dstfd_flags;
|
||||
int origfd_flags;
|
||||
int64_t srcfd_size;
|
||||
string fusedir;
|
||||
string fdin_path;
|
||||
string fdout_temp;
|
||||
vector<string> fdout_path;
|
||||
string srcfd_branch;
|
||||
string srcfd_filepath;
|
||||
string dstfd_filepath;
|
||||
string dstfd_tmp_filepath;
|
||||
vector<string> dstfd_branch;
|
||||
|
||||
fdin = *origfd_;
|
||||
srcfd = -1;
|
||||
dstfd = -1;
|
||||
|
||||
fdin_flags = fs::getfl(fdin);
|
||||
if(fdin_flags == -1)
|
||||
return -1;
|
||||
|
||||
rv = fs::findonfs(branches_,fusepath_,fdin,&fdin_path);
|
||||
rv = fs::findonfs(branches_,fusepath_,origfd_,&srcfd_branch);
|
||||
if(rv == -1)
|
||||
return -1;
|
||||
return -errno;
|
||||
|
||||
rv = createFunc_(branches_,fusepath_,&fdout_path);
|
||||
rv = createFunc_(branches_,fusepath_,&dstfd_branch);
|
||||
if(rv == -1)
|
||||
return -1;
|
||||
return -errno;
|
||||
|
||||
fdin_size = fs::file_size(fdin);
|
||||
if(fdin_size == -1)
|
||||
return -1;
|
||||
origfd_flags = fs::getfl(origfd_);
|
||||
if(origfd_flags == -1)
|
||||
return -errno;
|
||||
|
||||
if(fs::has_space(fdout_path[0],fdin_size) == false)
|
||||
return (errno=ENOSPC,-1);
|
||||
srcfd_size = fs::file_size(origfd_);
|
||||
if(srcfd_size == -1)
|
||||
return -errno;
|
||||
|
||||
if(fs::has_space(dstfd_branch[0],srcfd_size) == false)
|
||||
return -ENOSPC;
|
||||
|
||||
fusedir = fs::path::dirname(fusepath_);
|
||||
|
||||
rv = fs::clonepath(fdin_path,fdout_path[0],fusedir);
|
||||
rv = fs::clonepath(srcfd_branch,dstfd_branch[0],fusedir);
|
||||
if(rv == -1)
|
||||
return -1;
|
||||
return -ENOSPC;
|
||||
|
||||
fs::path::append(fdin_path,fusepath_);
|
||||
fdin = fs::open(fdin_path,O_RDONLY);
|
||||
if(fdin == -1)
|
||||
return -1;
|
||||
srcfd_filepath = srcfd_branch;
|
||||
fs::path::append(srcfd_filepath,fusepath_);
|
||||
srcfd = fs::open(srcfd_filepath,O_RDONLY);
|
||||
if(srcfd == -1)
|
||||
return -ENOSPC;
|
||||
|
||||
fs::path::append(fdout_path[0],fusepath_);
|
||||
fdout_temp = fdout_path[0];
|
||||
fdout = fs::mktemp(&fdout_temp,fdin_flags);
|
||||
if(fdout == -1)
|
||||
return -1;
|
||||
dstfd_filepath = dstfd_branch[0];
|
||||
fs::path::append(dstfd_filepath,fusepath_);
|
||||
dstfd_tmp_filepath = dstfd_filepath;
|
||||
dstfd = fs::mktemp(&dstfd_tmp_filepath,O_WRONLY);
|
||||
if(dstfd == -1)
|
||||
{
|
||||
fs::close(srcfd);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
rv = fs::clonefile(fdin,fdout);
|
||||
rv = fs::clonefile(srcfd,dstfd);
|
||||
if(rv == -1)
|
||||
goto cleanup;
|
||||
{
|
||||
fs::close(srcfd);
|
||||
fs::close(dstfd);
|
||||
fs::unlink(dstfd_tmp_filepath);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
rv = fs::rename(fdout_temp,fdout_path[0]);
|
||||
rv = fs::rename(dstfd_tmp_filepath,dstfd_filepath);
|
||||
if(rv == -1)
|
||||
goto cleanup;
|
||||
{
|
||||
fs::close(srcfd);
|
||||
fs::close(dstfd);
|
||||
fs::unlink(dstfd_tmp_filepath);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
// should we care if it fails?
|
||||
fs::unlink(fdin_path);
|
||||
fs::close(srcfd);
|
||||
fs::close(dstfd);
|
||||
|
||||
std::swap(*origfd_,fdout);
|
||||
fs::close(fdin);
|
||||
fs::close(fdout);
|
||||
dstfd_flags = ::cleanup_flags(origfd_flags);
|
||||
rv = fs::open(dstfd_filepath,dstfd_flags);
|
||||
if(rv == -1)
|
||||
{
|
||||
fs::unlink(dstfd_tmp_filepath);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
fs::unlink(srcfd_filepath);
|
||||
|
||||
cleanup:
|
||||
rv = errno;
|
||||
if(fdin != -1)
|
||||
fs::close(fdin);
|
||||
if(fdout != -1)
|
||||
fs::close(fdout);
|
||||
fs::unlink(fdout_temp);
|
||||
errno = rv;
|
||||
return -1;
|
||||
fs::close(origfd_);
|
||||
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +168,7 @@ namespace fs
|
||||
movefile(const Policy::Create &policy_,
|
||||
const Branches::CPtr &basepaths_,
|
||||
const string &fusepath_,
|
||||
int *origfd_)
|
||||
int origfd_)
|
||||
{
|
||||
return l::movefile(policy_,basepaths_,fusepath_,origfd_);
|
||||
}
|
||||
@ -145,7 +177,7 @@ namespace fs
|
||||
movefile_as_root(const Policy::Create &policy_,
|
||||
const Branches::CPtr &basepaths_,
|
||||
const string &fusepath_,
|
||||
int *origfd_)
|
||||
int origfd_)
|
||||
{
|
||||
const ugid::Set ugid(0,0);
|
||||
|
||||
|
@ -28,11 +28,11 @@ namespace fs
|
||||
movefile(const Policy::Create &policy,
|
||||
const Branches::CPtr &branches,
|
||||
const std::string &fusepath,
|
||||
int *origfd);
|
||||
int origfd);
|
||||
|
||||
int
|
||||
movefile_as_root(const Policy::Create &policy,
|
||||
const Branches::CPtr &branches,
|
||||
const std::string &fusepath,
|
||||
int *origfd);
|
||||
int origfd);
|
||||
}
|
||||
|
@ -44,28 +44,10 @@ namespace l
|
||||
|
||||
static
|
||||
int
|
||||
write_regular(const int fd_,
|
||||
const void *buf_,
|
||||
const size_t count_,
|
||||
const off_t offset_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = fs::pwrite(fd_,buf_,count_,offset_);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
if(rv == 0)
|
||||
return 0;
|
||||
|
||||
return count_;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
write_direct_io(const int fd_,
|
||||
const void *buf_,
|
||||
const size_t count_,
|
||||
const off_t offset_)
|
||||
write(const int fd_,
|
||||
const void *buf_,
|
||||
const size_t count_,
|
||||
const off_t offset_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
@ -78,8 +60,7 @@ namespace l
|
||||
|
||||
static
|
||||
int
|
||||
move_and_write(WriteFunc func_,
|
||||
const char *buf_,
|
||||
move_and_write(const char *buf_,
|
||||
const size_t count_,
|
||||
const off_t offset_,
|
||||
FileInfo *fi_,
|
||||
@ -94,17 +75,18 @@ namespace l
|
||||
rv = fs::movefile_as_root(cfg->moveonenospc.policy,
|
||||
cfg->branches,
|
||||
fi_->fusepath,
|
||||
&fi_->fd);
|
||||
if(rv == -1)
|
||||
fi_->fd);
|
||||
if(rv < 0)
|
||||
return err_;
|
||||
|
||||
return func_(fi_->fd,buf_,count_,offset_);
|
||||
fi_->fd = rv;
|
||||
|
||||
return l::write(fi_->fd,buf_,count_,offset_);
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
write(const fuse_file_info_t *ffi_,
|
||||
WriteFunc func_,
|
||||
const char *buf_,
|
||||
const size_t count_,
|
||||
const off_t offset_)
|
||||
@ -114,9 +96,9 @@ namespace l
|
||||
|
||||
fi = reinterpret_cast<FileInfo*>(ffi_->fh);
|
||||
|
||||
rv = func_(fi->fd,buf_,count_,offset_);
|
||||
rv = l::write(fi->fd,buf_,count_,offset_);
|
||||
if(l::out_of_space(-rv))
|
||||
rv = l::move_and_write(func_,buf_,count_,offset_,fi,rv);
|
||||
rv = l::move_and_write(buf_,count_,offset_,fi,rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -130,13 +112,7 @@ namespace FUSE
|
||||
size_t count_,
|
||||
off_t offset_)
|
||||
{
|
||||
WriteFunc wf;
|
||||
|
||||
wf = ((ffi_->direct_io) ?
|
||||
l::write_direct_io :
|
||||
l::write_regular);
|
||||
|
||||
return l::write(ffi_,wf,buf_,count_,offset_);
|
||||
return l::write(ffi_,buf_,count_,offset_);
|
||||
}
|
||||
|
||||
int
|
||||
|
Loading…
x
Reference in New Issue
Block a user