ceph-fuse: link to libfuse3 if fuse3 is installed

Fixes: https://tracker.ceph.com/issues/44891
Signed-off-by: Xiubo Li <xiubli@redhat.com>
This commit is contained in:
Xiubo Li 2020-04-15 02:21:44 -04:00
parent 32a45b624b
commit cb0a600acf
5 changed files with 228 additions and 37 deletions

View File

@ -41,6 +41,7 @@
#include <fcntl.h>
#include <fuse.h>
#include <fuse_lowlevel.h>
#define dout_context g_ceph_context
@ -51,7 +52,12 @@ static void fuse_usage()
"-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);
@ -105,7 +111,12 @@ int main(int argc, const char **argv, const char *envp[]) {
};
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);

View File

@ -85,9 +85,13 @@ public:
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;
@ -418,7 +422,11 @@ static void fuse_ll_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
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 {
@ -504,7 +512,11 @@ static void fuse_ll_symlink(fuse_req_t req, const char *existing,
}
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);
@ -916,8 +928,12 @@ static void ino_invalidate_cb(void *handle, vinodeno_t vino, int64_t off,
#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,
@ -929,7 +945,11 @@ 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
@ -941,7 +961,12 @@ static int remount_cb(void *handle)
// 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);
@ -1043,14 +1068,19 @@ const static struct fuse_lowlevel_ops fuse_ll_oper = {
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()
@ -1060,6 +1090,15 @@ 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)
@ -1068,6 +1107,7 @@ void CephFuse::Handle::finalize()
fuse_session_destroy(se);
if (ch)
fuse_unmount(mountpoint, ch);
#endif
pthread_key_delete(fuse_req_key);
}
@ -1094,14 +1134,16 @@ int CephFuse::Handle::init(int argc, const char *argv[])
"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_atomic_o_trunc = client->cct->_conf.get_val<bool>(
"fuse_atomic_o_trunc");
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");
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");
if (fuse_allow_other) {
newargv[newargc++] = "-o";
@ -1112,6 +1154,7 @@ int CephFuse::Handle::init(int argc, const char *argv[])
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";
@ -1126,6 +1169,7 @@ int CephFuse::Handle::init(int argc, const char *argv[])
newargv[newargc++] = "-o";
newargv[newargc++] = "atomic_o_trunc";
}
#endif
#endif
if (fuse_debug)
newargv[newargc++] = "-d";
@ -1137,7 +1181,11 @@ int CephFuse::Handle::init(int argc, const char *argv[])
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);
@ -1151,6 +1199,9 @@ int CephFuse::Handle::init(int argc, const char *argv[])
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;
@ -1158,6 +1209,7 @@ int CephFuse::Handle::start()
}
se = fuse_lowlevel_new(&args, &fuse_ll_oper, sizeof(fuse_ll_oper), this);
#endif
if (!se) {
derr << "fuse_lowlevel_new failed" << dendl;
return EDOM;
@ -1170,7 +1222,14 @@ int CephFuse::Handle::start()
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 = {
@ -1196,7 +1255,11 @@ int CephFuse::Handle::loop()
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);
}
@ -1326,8 +1389,13 @@ void CephFuse::finalize()
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 "";
}

32
src/include/ceph_fuse.h Normal file
View File

@ -0,0 +1,32 @@
// -*- 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 */

View File

@ -9,6 +9,8 @@
#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>
@ -40,7 +42,9 @@ using ceph::bufferptr;
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;
};
@ -238,7 +242,11 @@ static int parse_fn(CephContext* cct, const char *path, coll_t *cid,
}
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);
@ -395,7 +403,11 @@ static int os_readdir(const char *path,
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);
@ -420,11 +432,11 @@ static int os_readdir(const char *path,
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;
}
@ -436,28 +448,28 @@ static int os_readdir(const char *path,
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;
@ -512,7 +524,7 @@ static int os_readdir(const char *path,
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;
}
@ -535,7 +547,7 @@ static int os_readdir(const char *path,
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;
}
@ -553,7 +565,7 @@ static int os_readdir(const char *path,
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;
}
@ -790,7 +802,11 @@ static int os_mkdir(const char *path, mode_t mode)
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);
@ -1061,7 +1077,11 @@ static int os_unlink(const char *path)
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);
@ -1127,7 +1147,9 @@ static int os_statfs(const char *path, struct statvfs *stbuf)
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,
@ -1138,7 +1160,9 @@ static struct fuse_operations fs_oper = {
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,
@ -1187,16 +1211,38 @@ int FuseStore::start()
"-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;
@ -1210,6 +1256,7 @@ int FuseStore::start()
derr << __func__ << " fuse_new failed" << dendl;
return -EIO;
}
#endif
fuse_thread.create("fusestore");
dout(10) << __func__ << " done" << dendl;
@ -1229,7 +1276,11 @@ int FuseStore::loop()
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;

View File

@ -32,6 +32,7 @@
#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"
@ -244,7 +245,11 @@ static int count_images(void)
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;
@ -456,11 +461,15 @@ static void rbdfs_readdir_cb(void *_info, const char *name)
{
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 };
@ -472,8 +481,8 @@ static int rbdfs_readdir(const char *path, void *buf, fuse_fill_dir_t 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;
@ -488,7 +497,11 @@ static int rbdfs_releasedir(const char *path, struct fuse_file_info *fi)
}
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;
@ -570,7 +583,11 @@ rbdfs_create(const char *path, mode_t mode, struct fuse_file_info *fi)
}
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;
@ -587,7 +604,11 @@ rbdfs_rename(const char *path, const char *destname)
}
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;
@ -609,7 +630,11 @@ rbdfs_unlink(const char *path)
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;
@ -724,7 +749,9 @@ rbdfs_listxattr(const char *path, char *list, size_t len)
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,
@ -757,8 +784,10 @@ const static struct fuse_operations rbdfs_oper = {
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 */