move on enospc when writing feature. closes #141

This feature mimics the standard mhddfs behavior but is more thorough.
If a write fails and the errno is set to ENOSPC then mergerfs will (if
the feature is enabled) attempt to move the file to the drive with
the most free space but only if it has enough room for the file plus
the amount to be written. If that transfer is successful it will then
unlink the original file and attempt the previously failed write again.

The copy includes copying the path and file including the acls, owners,
attributes, extended attributes, and timestamps.
This commit is contained in:
Antonio SJ Musumeci 2015-09-15 18:49:18 -04:00
parent 4e5578de9c
commit 5808ab7795
66 changed files with 1837 additions and 665 deletions

View file

@ -25,11 +25,25 @@
#if WRITE_BUF
#include <fuse.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string>
#include <vector>
#include "config.hpp"
#include "fileinfo.hpp"
#include "fs_movefile.hpp"
#include "policy.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include "write.hpp"
using std::string;
using std::vector;
using namespace mergerfs;
static
int
_write_buf(const int fd,
@ -58,9 +72,31 @@ namespace mergerfs
off_t offset,
fuse_file_info *ffi)
{
return _write_buf(ffi->fh,
*src,
offset);
int rv;
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
rv = _write_buf(fi->fd,*src,offset);
if(rv == -ENOSPC)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
if(config.moveonenospc)
{
size_t extra;
const ugid::Set ugid(0,0);
const rwlock::ReadGuard readlock(&config.srcmountslock);
extra = fuse_buf_size(src);
rv = fs::movefile(config.srcmounts,fusepath,extra,fi->fd);
if(rv == -1)
return -ENOSPC;
rv = _write_buf(fi->fd,*src,offset);
}
}
return rv;
}
}
}