Browse Source

Merge pull request #563 from trapexit/ioctl

make ioctl on directories use open policy
pull/564/head
trapexit 6 years ago
committed by GitHub
parent
commit
40319081e0
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 8
      man/mergerfs.1
  3. 159
      src/ioctl.cpp

2
README.md

@ -181,7 +181,7 @@ When using policies which are based on a branch's available space the base path
| search | access, getattr, getxattr, ioctl, listxattr, open, readlink |
| N/A | fallocate, fgetattr, fsync, ftruncate, ioctl, read, readdir, release, statfs, write |
Due to FUSE limitations **ioctl** behaves differently if its acting on a directory. It'll use the **getattr** policy to find and open the directory before issuing the **ioctl**. In other cases where something may be searched (to confirm a directory exists across all source mounts) **getattr** will also be used.
In cases where something may be searched (to confirm a directory exists across all source mounts) **getattr** will be used.
#### Path Preservation

8
man/mergerfs.1

@ -426,12 +426,8 @@ statfs, write
T}
.TE
.PP
Due to FUSE limitations \f[B]ioctl\f[] behaves differently if its acting
on a directory.
It\[aq]ll use the \f[B]getattr\f[] policy to find and open the directory
before issuing the \f[B]ioctl\f[].
In other cases where something may be searched (to confirm a directory
exists across all source mounts) \f[B]getattr\f[] will also be used.
In cases where something may be searched (to confirm a directory exists
across all source mounts) \f[B]getattr\f[] will be used.
.SS Path Preservation
.PP
Policies, as described below, are of two basic types.

159
src/ioctl.cpp

@ -14,13 +14,6 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <fuse.h>
#include <string>
#include <vector>
#include <fcntl.h>
#include "config.hpp"
#include "dirinfo.hpp"
#include "errno.hpp"
@ -32,33 +25,42 @@
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
#include <fcntl.h>
using std::string;
using std::vector;
using namespace mergerfs;
static
int
_ioctl(const int fd,
const unsigned long cmd,
void *data)
namespace local
{
int rv;
static
int
ioctl(const int fd_,
const unsigned long cmd_,
void *data_)
{
int rv;
rv = fs::ioctl(fd,cmd,data);
rv = fs::ioctl(fd_,cmd_,data_);
return ((rv == -1) ? -errno : rv);
}
return ((rv == -1) ? -errno : rv);
}
static
int
_ioctl_file(fuse_file_info *ffi,
const unsigned long cmd,
void *data)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
static
int
ioctl_file(fuse_file_info *ffi_,
const unsigned long cmd_,
void *data_)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return _ioctl(fi->fd,cmd,data);
}
return local::ioctl(fi->fd,cmd_,data_);
}
#ifdef FUSE_IOCTL_DIR
@ -66,77 +68,78 @@ _ioctl_file(fuse_file_info *ffi,
#define O_NOATIME 0
#endif
static
int
_ioctl_dir_base(Policy::Func::Search searchFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const unsigned long cmd,
void *data)
{
int fd;
int rv;
string fullpath;
vector<const string*> basepaths;
static
int
ioctl_dir_base(Policy::Func::Search searchFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const unsigned long cmd_,
void *data_)
{
int fd;
int rv;
string fullpath;
vector<const string*> basepaths;
rv = searchFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
fs::path::make(basepaths[0],fusepath,fullpath);
fs::path::make(basepaths[0],fusepath_,fullpath);
const int flags = O_RDONLY | O_NOATIME | O_NONBLOCK;
fd = fs::open(fullpath,flags);
if(fd == -1)
return -errno;
const int flags = O_RDONLY | O_NOATIME | O_NONBLOCK;
fd = fs::open(fullpath,flags);
if(fd == -1)
return -errno;
rv = _ioctl(fd,cmd,data);
rv = local::ioctl(fd,cmd_,data_);
fs::close(fd);
fs::close(fd);
return rv;
}
return rv;
}
static
int
_ioctl_dir(fuse_file_info *ffi,
const unsigned long cmd,
void *data)
{
DirInfo *di = reinterpret_cast<DirInfo*>(ffi->fh);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return _ioctl_dir_base(config.getattr,
config.branches,
config.minfreespace,
di->fusepath.c_str(),
cmd,
data);
}
static
int
ioctl_dir(fuse_file_info *ffi_,
const unsigned long cmd_,
void *data_)
{
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return local::ioctl_dir_base(config.open,
config.branches,
config.minfreespace,
di->fusepath.c_str(),
cmd_,
data_);
}
#endif
}
namespace mergerfs
{
namespace fuse
{
int
ioctl(const char *fusepath,
int cmd,
void *arg,
fuse_file_info *ffi,
unsigned int flags,
void *data)
ioctl(const char *fusepath_,
int cmd_,
void *arg_,
fuse_file_info *ffi_,
unsigned int flags_,
void *data_)
{
#ifdef FUSE_IOCTL_DIR
if(flags & FUSE_IOCTL_DIR)
return ::_ioctl_dir(ffi,cmd,data);
if(flags_ & FUSE_IOCTL_DIR)
return local::ioctl_dir(ffi_,cmd_,data_);
#endif
return ::_ioctl_file(ffi,cmd,data);
return local::ioctl_file(ffi_,cmd_,data_);
}
}
}
Loading…
Cancel
Save