Add fuse_set_feature_flag() / fuse_unset_feature_flag

Simplify setting feature flags a bit by adding a helper
function.

Also move the check for valid flags into a funtion we can re-use
in a later patch.
This commit is contained in:
Bernd Schubert 2024-09-19 15:03:55 +02:00 committed by Bernd Schubert
parent 82cca94678
commit 15f5c81123
3 changed files with 41 additions and 20 deletions

View File

@ -190,36 +190,29 @@ static int get_fs_fd(fuse_ino_t ino) {
static void sfs_init(void *userdata, fuse_conn_info *conn) {
(void)userdata;
if (fs.passthrough && conn->capable & FUSE_CAP_PASSTHROUGH)
conn->want |= FUSE_CAP_PASSTHROUGH;
else
if (!fuse_set_feature_flag(conn, FUSE_CAP_PASSTHROUGH))
fs.passthrough = false;
/* Passthrough and writeback cache are conflicting modes */
if (fs.timeout && !fs.passthrough &&
conn->capable & FUSE_CAP_WRITEBACK_CACHE)
conn->want |= FUSE_CAP_WRITEBACK_CACHE;
if (fs.timeout && !fs.passthrough)
fuse_set_feature_flag(conn, FUSE_CAP_WRITEBACK_CACHE);
if (conn->capable & FUSE_CAP_FLOCK_LOCKS)
conn->want |= FUSE_CAP_FLOCK_LOCKS;
fuse_set_feature_flag(conn, FUSE_CAP_FLOCK_LOCKS);
if (fs.nosplice) {
// FUSE_CAP_SPLICE_READ is enabled in libfuse3 by default,
// see do_init() in in fuse_lowlevel.c
// Just unset both, in case FUSE_CAP_SPLICE_WRITE would also get enabled
// by default.
conn->want &= ~FUSE_CAP_SPLICE_READ;
conn->want &= ~FUSE_CAP_SPLICE_WRITE;
fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_READ);
fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_WRITE);
} else {
if (conn->capable & FUSE_CAP_SPLICE_WRITE)
conn->want |= FUSE_CAP_SPLICE_WRITE;
if (conn->capable & FUSE_CAP_SPLICE_READ)
conn->want |= FUSE_CAP_SPLICE_READ;
fuse_set_feature_flag(conn, FUSE_CAP_SPLICE_WRITE);
fuse_set_feature_flag(conn, FUSE_CAP_SPLICE_READ);
}
/* This is a local file system - no network coherency needed */
if (conn->capable & FUSE_CAP_DIRECT_IO_ALLOW_MMAP)
conn->want |= FUSE_CAP_DIRECT_IO_ALLOW_MMAP;
fuse_set_feature_flag(conn, FUSE_CAP_DIRECT_IO_ALLOW_MMAP);
/* Disable the receiving and processing of FUSE_INTERRUPT requests */
conn->no_interrupt = 1;

View File

@ -7,6 +7,7 @@
/** @file */
#include <stdbool.h>
#if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_)
#error "Never include <fuse_common.h> directly; use <fuse.h> or <fuse_lowlevel.h> instead."
#endif
@ -1034,6 +1035,23 @@ void fuse_loop_cfg_convert(struct fuse_loop_config *config,
struct fuse_loop_config_v1 *v1_conf);
#endif
static inline bool fuse_set_feature_flag(struct fuse_conn_info *conn,
uint64_t flag)
{
if (conn->capable & flag) {
conn->want |= flag;
return true;
}
return false;
}
static inline void fuse_unset_feature_flag(struct fuse_conn_info *conn,
uint64_t flag)
{
conn->want &= ~flag;
}
/* ----------------------------------------------------------- *
* Compatibility stuff *
* ----------------------------------------------------------- */

View File

@ -9,6 +9,7 @@
See the file COPYING.LIB
*/
#include <stdbool.h>
#define _GNU_SOURCE
#include "fuse_config.h"
@ -1965,6 +1966,18 @@ static void do_lseek(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fuse_reply_err(req, ENOSYS);
}
static bool want_flags_valid(uint64_t capable, uint64_t want)
{
uint64_t unknown_flags = want & (~capable);
if (unknown_flags != 0) {
fuse_log(FUSE_LOG_ERR,
"fuse: unknown connection 'want' flags: 0x%08lx\n",
unknown_flags);
return false;
}
return true;
}
/* Prevent bogus data races (bogus since "init" is called before
* multi-threading becomes relevant */
static __attribute__((no_sanitize("thread")))
@ -2121,10 +2134,7 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (se->op.init)
se->op.init(se->userdata, &se->conn);
if (se->conn.want & (~se->conn.capable)) {
fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities "
"0x%x that are not supported by kernel, aborting.\n",
se->conn.want & (~se->conn.capable));
if (!want_flags_valid(se->conn.capable, se->conn.want)) {
fuse_reply_err(req, EPROTO);
se->error = -EPROTO;
fuse_session_exit(se);