#include <fcntl.h>
#include <fuse.h>
+#include <fuse_lowlevel.h>
#define dout_context g_ceph_context
"-h",
};
struct fuse_args args = FUSE_ARGS_INIT(2, (char**)argv);
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ struct fuse_cmdline_opts opts = {};
+ if (fuse_parse_cmdline(&args, &opts) == -1) {
+#else
if (fuse_parse_cmdline(&args, nullptr, nullptr, nullptr) == -1) {
+#endif
derr << "fuse_parse_cmdline failed." << dendl;
}
ceph_assert(args.allocated);
};
struct fuse_args fargs = FUSE_ARGS_INIT(2, (char**)tmpargv);
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ struct fuse_cmdline_opts opts = {};
+ if (fuse_parse_cmdline(&fargs, &opts) == -1) {
+#else
if (fuse_parse_cmdline(&fargs, nullptr, nullptr, nullptr) == -1) {
+#endif
derr << "fuse_parse_cmdline failed." << dendl;
}
ceph_assert(fargs.allocated);
int fd_on_success;
Client *client;
- struct fuse_chan *ch;
struct fuse_session *se;
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ struct fuse_cmdline_opts opts;
+#else
+ struct fuse_chan *ch;
char *mountpoint;
+#endif
ceph::mutex stag_lock = ceph::make_mutex("fuse_ll.cc stag_lock");
int last_stag;
if (cfuse->fino_snap(parent) == CEPH_SNAPDIR &&
fuse_multithreaded && fuse_syncfs_on_mksnap) {
int err = 0;
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ int fd = ::open(cfuse->opts.mountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+#else
int fd = ::open(cfuse->mountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
+#endif
if (fd < 0) {
err = errno;
} else {
}
static void fuse_ll_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
- fuse_ino_t newparent, const char *newname)
+ fuse_ino_t newparent, const char *newname
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , unsigned int flags
+#endif
+ )
{
CephFuse::Handle *cfuse = fuse_ll_req_prepare(req);
const struct fuse_ctx *ctx = fuse_req_ctx(req);
#if FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
CephFuse::Handle *cfuse = (CephFuse::Handle *)handle;
fuse_ino_t fino = cfuse->make_fake_ino(vino.ino, vino.snapid);
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ fuse_lowlevel_notify_inval_inode(cfuse->se, fino, off, len);
+#else
fuse_lowlevel_notify_inval_inode(cfuse->ch, fino, off, len);
#endif
+#endif
}
static void dentry_invalidate_cb(void *handle, vinodeno_t dirino,
fuse_ino_t fino = 0;
if (ino.ino != inodeno_t())
fino = cfuse->make_fake_ino(ino.ino, ino.snapid);
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ fuse_lowlevel_notify_delete(cfuse->se, fdirino, fino, name.c_str(), name.length());
+#else
fuse_lowlevel_notify_delete(cfuse->ch, fdirino, fino, name.c_str(), name.length());
+#endif
#elif FUSE_VERSION >= FUSE_MAKE_VERSION(2, 8)
fuse_lowlevel_notify_inval_entry(cfuse->ch, fdirino, name.c_str(), name.length());
#endif
// trims all unused dentries in the file system
char cmd[128+PATH_MAX];
CephFuse::Handle *cfuse = (CephFuse::Handle *)handle;
- snprintf(cmd, sizeof(cmd), "LIBMOUNT_FSTAB=/dev/null mount -i -o remount %s", cfuse->mountpoint);
+ snprintf(cmd, sizeof(cmd), "LIBMOUNT_FSTAB=/dev/null mount -i -o remount %s",
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ cfuse->opts.mountpoint);
+#else
+ cfuse->mountpoint);
+#endif
int r = system(cmd);
if (r != 0 && r != -1) {
r = WEXITSTATUS(r);
CephFuse::Handle::Handle(Client *c, int fd) :
fd_on_success(fd),
client(c),
- ch(NULL),
se(NULL),
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
+ ch(NULL),
mountpoint(NULL),
+#endif
last_stag(0)
{
snap_stag_map[CEPH_NOSNAP] = 0;
stag_snap_map[0] = CEPH_NOSNAP;
memset(&args, 0, sizeof(args));
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ memset(&opts, 0, sizeof(opts));
+#endif
}
CephFuse::Handle::~Handle()
void CephFuse::Handle::finalize()
{
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ if (se) {
+ fuse_remove_signal_handlers(se);
+ fuse_session_unmount(se);
+ fuse_session_destroy(se);
+ }
+ if (opts.mountpoint)
+ free(opts.mountpoint);
+#else
if (se)
fuse_remove_signal_handlers(se);
if (ch)
fuse_session_destroy(se);
if (ch)
fuse_unmount(mountpoint, ch);
+#endif
pthread_key_delete(fuse_req_key);
}
"fuse_allow_other");
auto fuse_default_permissions = client->cct->_conf.get_val<bool>(
"fuse_default_permissions");
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
auto fuse_big_writes = client->cct->_conf.get_val<bool>(
"fuse_big_writes");
+ auto fuse_max_write = client->cct->_conf.get_val<Option::size_t>(
+ "fuse_max_write");
auto fuse_atomic_o_trunc = client->cct->_conf.get_val<bool>(
"fuse_atomic_o_trunc");
+#endif
auto fuse_debug = client->cct->_conf.get_val<bool>(
"fuse_debug");
- auto fuse_max_write = client->cct->_conf.get_val<Option::size_t>(
- "fuse_max_write");
if (fuse_allow_other) {
newargv[newargc++] = "-o";
newargv[newargc++] = "default_permissions";
}
#if defined(__linux__)
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
if (fuse_big_writes) {
newargv[newargc++] = "-o";
newargv[newargc++] = "big_writes";
newargv[newargc++] = "-o";
newargv[newargc++] = "atomic_o_trunc";
}
+#endif
#endif
if (fuse_debug)
newargv[newargc++] = "-d";
struct fuse_args a = FUSE_ARGS_INIT(newargc, (char**)newargv);
args = a; // Roundabout construction b/c FUSE_ARGS_INIT is for initialization not assignment
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ if (fuse_parse_cmdline(&args, &opts) == -1) {
+#else
if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) == -1) {
+#endif
derr << "fuse_parse_cmdline failed." << dendl;
fuse_opt_free_args(&args);
free(newargv);
int CephFuse::Handle::start()
{
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ se = fuse_session_new(&args, &fuse_ll_oper, sizeof(fuse_ll_oper), this);
+#else
ch = fuse_mount(mountpoint, &args);
if (!ch) {
derr << "fuse_mount(mountpoint=" << mountpoint << ") failed." << dendl;
}
se = fuse_lowlevel_new(&args, &fuse_ll_oper, sizeof(fuse_ll_oper), this);
+#endif
if (!se) {
derr << "fuse_lowlevel_new failed" << dendl;
return EDOM;
return ENOSYS;
}
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ if (fuse_session_mount(se, opts.mountpoint) != 0) {
+ derr << "fuse_session_mount failed" << dendl;
+ return ENOSYS;
+ }
+#else
fuse_session_add_chan(se, ch);
+#endif
struct client_callback_args args = {
auto fuse_multithreaded = client->cct->_conf.get_val<bool>(
"fuse_multithreaded");
if (fuse_multithreaded) {
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ return fuse_session_loop_mt(se, opts.clone_fd);
+#else
return fuse_session_loop_mt(se);
+#endif
} else {
return fuse_session_loop(se);
}
std::string CephFuse::get_mount_point() const
{
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ if (_handle->opts.mountpoint) {
+ return _handle->opts.mountpoint;
+#else
if (_handle->mountpoint) {
return _handle->mountpoint;
+#endif
} else {
return "";
}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2012 Inktank Storage, Inc.
+ * Copyright (C) 2014 Red Hat <contact@redhat.com>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ */
+#ifndef CEPH_FUSE_H
+#define CEPH_FUSE_H
+
+#define FUSE_USE_VERSION 30
+#include "acconfig.h"
+#include <fuse.h>
+
+static inline int filler_compat(fuse_fill_dir_t filler,
+ void *buf, const char *name,
+ const struct stat *stbuf,
+ off_t off)
+{
+ return filler(buf, name, stbuf, off
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , static_cast<enum fuse_fill_dir_flags>(0)
+#endif
+ );
+}
+#endif /* CEPH_FUSE_H */
#define FUSE_USE_VERSION 30
#include <fuse.h>
+#include <fuse_lowlevel.h>
+#include "include/ceph_fuse.h"
#include <sys/types.h>
#include <sys/stat.h>
struct fs_info {
struct fuse_args args;
struct fuse *f;
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
struct fuse_chan *ch;
+#endif
char *mountpoint;
};
}
-static int os_getattr(const char *path, struct stat *stbuf)
+static int os_getattr(const char *path, struct stat *stbuf
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
fuse_context *fc = fuse_get_context();
FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
void *buf,
fuse_fill_dir_t filler,
off_t offset,
- struct fuse_file_info *fi)
+ struct fuse_file_info *fi
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , enum fuse_readdir_flags
+#endif
+ )
{
fuse_context *fc = fuse_get_context();
FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
switch (t) {
case FN_ROOT:
{
- filler(buf, "type", NULL, 0);
+ filler_compat(filler, buf, "type", NULL, 0);
vector<coll_t> cls;
fs->store->list_collections(cls);
for (auto c : cls) {
- int r = filler(buf, stringify(c).c_str(), NULL, 0);
+ int r = filler_compat(filler, buf, stringify(c).c_str(), NULL, 0);
if (r > 0)
break;
}
if (!ch) {
return -ENOENT;
}
- filler(buf, "bitwise_hash_start", NULL, 0);
+ filler_compat(filler, buf, "bitwise_hash_start", NULL, 0);
if (fs->store->collection_bits(ch) >= 0) {
- filler(buf, "bitwise_hash_end", NULL, 0);
- filler(buf, "bitwise_hash_bits", NULL, 0);
+ filler_compat(filler, buf, "bitwise_hash_end", NULL, 0);
+ filler_compat(filler, buf, "bitwise_hash_bits", NULL, 0);
}
- filler(buf, "all", NULL, 0);
- filler(buf, "by_bitwise_hash", NULL, 0);
+ filler_compat(filler, buf, "all", NULL, 0);
+ filler_compat(filler, buf, "by_bitwise_hash", NULL, 0);
spg_t pgid;
if (cid.is_pg(&pgid) &&
fs->store->exists(ch, pgid.make_pgmeta_oid())) {
- filler(buf, "pgmeta", NULL, 0);
+ filler_compat(filler, buf, "pgmeta", NULL, 0);
}
}
break;
case FN_OBJECT:
{
- filler(buf, "bitwise_hash", NULL, 0);
- filler(buf, "data", NULL, 0);
- filler(buf, "omap", NULL, 0);
- filler(buf, "attr", NULL, 0);
- filler(buf, "omap_header", NULL, 0);
+ filler_compat(filler, buf, "bitwise_hash", NULL, 0);
+ filler_compat(filler, buf, "data", NULL, 0);
+ filler_compat(filler, buf, "omap", NULL, 0);
+ filler_compat(filler, buf, "attr", NULL, 0);
+ filler_compat(filler, buf, "omap_header", NULL, 0);
}
break;
uint64_t cur_off = ((uint64_t)bitwise_hash << hash_shift) |
(uint64_t)hashoff;
string s = stringify(p);
- r = filler(buf, s.c_str(), NULL, cur_off);
+ r = filler_compat(filler, buf, s.c_str(), NULL, cur_off);
if (r)
break;
}
continue;
}
++offset;
- int r = filler(buf, k.c_str(), NULL, offset);
+ int r = filler_compat(filler, buf, k.c_str(), NULL, offset);
if (r)
break;
}
continue;
}
++offset;
- int r = filler(buf, a.first.c_str(), NULL, offset);
+ int r = filler_compat(filler, buf, a.first.c_str(), NULL, offset);
if (r)
break;
}
return 0;
}
-static int os_chmod(const char *path, mode_t mode)
+static int os_chmod(const char *path, mode_t mode
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
fuse_context *fc = fuse_get_context();
FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
return 0;
}
-static int os_truncate(const char *path, off_t size)
+static int os_truncate(const char *path, off_t size
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
fuse_context *fc = fuse_get_context();
FuseStore *fs = static_cast<FuseStore*>(fc->private_data);
static struct fuse_operations fs_oper = {
getattr: os_getattr,
readlink: 0,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
getdir: 0,
+#endif
mknod: 0,
mkdir: os_mkdir,
unlink: os_unlink,
chmod: os_chmod,
chown: 0,
truncate: os_truncate,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
utime: 0,
+#endif
open: os_open,
read: os_read,
write: os_write,
"-d", // debug
};
int c = 3;
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ int rc;
+ struct fuse_cmdline_opts opts = {};
+#endif
auto fuse_debug = store->cct->_conf.get_val<bool>("fuse_debug");
if (fuse_debug)
++c;
fuse_args a = FUSE_ARGS_INIT(c, (char**)v);
info->args = a;
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ if (fuse_parse_cmdline(&info->args, &opts) == -1) {
+#else
if (fuse_parse_cmdline(&info->args, &info->mountpoint, NULL, NULL) == -1) {
+#endif
derr << __func__ << " failed to parse args" << dendl;
return -EINVAL;
}
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ info->mountpoint = opts.mountpoint;
+ info->f = fuse_new(&info->args, &fs_oper, sizeof(fs_oper), (void*)this);
+ if (!info->f) {
+ derr << __func__ << " fuse_new failed" << dendl;
+ return -EIO;
+ }
+
+ rc = fuse_mount(info->f, info->mountpoint);
+ if (rc != 0) {
+ derr << __func__ << " fuse_mount failed" << dendl;
+ return -EIO;
+ }
+#else
info->ch = fuse_mount(info->mountpoint, &info->args);
if (!info->ch) {
derr << __func__ << " fuse_mount failed" << dendl;
derr << __func__ << " fuse_new failed" << dendl;
return -EIO;
}
+#endif
fuse_thread.create("fusestore");
dout(10) << __func__ << " done" << dendl;
int FuseStore::stop()
{
dout(10) << __func__ << " enter" << dendl;
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ fuse_unmount(info->f);
+#else
fuse_unmount(info->mountpoint, info->ch);
+#endif
fuse_thread.join();
fuse_destroy(info->f);
dout(10) << __func__ << " exit" << dendl;
#include "common/ceph_argparse.h"
#include "common/ceph_context.h"
+#include "include/ceph_fuse.h"
#include "global/global_init.h"
#include "global/global_context.h"
extern "C" {
-static int rbdfs_getattr(const char *path, struct stat *stbuf)
+static int rbdfs_getattr(const char *path, struct stat *stbuf
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
int fd;
time_t now;
{
struct rbdfs_readdir_info *info = (struct rbdfs_readdir_info*) _info;
- info->filler(info->buf, name, NULL, 0);
+ filler_compat(info->filler, info->buf, name, NULL, 0);
}
static int rbdfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
- off_t offset, struct fuse_file_info *fi)
+ off_t offset, struct fuse_file_info *fi
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , enum fuse_readdir_flags
+#endif
+ )
{
struct rbdfs_readdir_info info = { buf, filler };
if (strcmp(path, "/") != 0)
return -ENOENT;
- filler(buf, ".", NULL, 0);
- filler(buf, "..", NULL, 0);
+ filler_compat(filler, buf, ".", NULL, 0);
+ filler_compat(filler, buf, "..", NULL, 0);
iter_images(&info, rbdfs_readdir_cb);
return 0;
}
void *
-rbdfs_init(struct fuse_conn_info *conn)
+rbdfs_init(struct fuse_conn_info *conn
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_config *cfg
+#endif
+ )
{
int ret;
}
int
-rbdfs_rename(const char *path, const char *destname)
+rbdfs_rename(const char *path, const char *destname
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , unsigned int flags
+#endif
+ )
{
int r;
}
int
-rbdfs_utimens(const char *path, const struct timespec tv[2])
+rbdfs_utimens(const char *path, const struct timespec tv[2]
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
// called on create; not relevant
return 0;
int
-rbdfs_truncate(const char *path, off_t size)
+rbdfs_truncate(const char *path, off_t size
+#if FUSE_VERSION >= FUSE_MAKE_VERSION(3, 0)
+ , struct fuse_file_info *fi
+#endif
+ )
{
int fd;
int r;
const static struct fuse_operations rbdfs_oper = {
getattr: rbdfs_getattr,
readlink: 0,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
getdir: 0,
+#endif
mknod: 0,
mkdir: 0,
unlink: rbdfs_unlink,
destroy: rbdfs_destroy,
access: 0,
create: rbdfs_create,
+#if FUSE_VERSION < FUSE_MAKE_VERSION(3, 0)
ftruncate: 0,
fgetattr: 0,
+#endif
lock: 0,
utimens: rbdfs_utimens,
/* skip unimplemented */