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. 83
      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 | | search | access, getattr, getxattr, ioctl, listxattr, open, readlink |
| N/A | fallocate, fgetattr, fsync, ftruncate, ioctl, read, readdir, release, statfs, write | | 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 #### Path Preservation

8
man/mergerfs.1

@ -426,12 +426,8 @@ statfs, write
T} T}
.TE .TE
.PP .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 .SS Path Preservation
.PP .PP
Policies, as described below, are of two basic types. Policies, as described below, are of two basic types.

83
src/ioctl.cpp

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