From: Bernd Schubert Date: Thu, 19 Sep 2024 13:03:55 +0000 (+0200) Subject: Add fuse_set_feature_flag() / fuse_unset_feature_flag X-Git-Tag: fuse-3.17.1-rc0~51 X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=15f5c811239abca80eda2d988be7a9a9848f7c10;p=qemu-gpiodev%2Flibfuse.git 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. --- diff --git a/example/passthrough_hp.cc b/example/passthrough_hp.cc index bfaada5..1f6647f 100644 --- a/example/passthrough_hp.cc +++ b/example/passthrough_hp.cc @@ -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; diff --git a/include/fuse_common.h b/include/fuse_common.h index 38bac4e..1abac5a 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -7,6 +7,7 @@ /** @file */ +#include #if !defined(FUSE_H_) && !defined(FUSE_LOWLEVEL_H_) #error "Never include directly; use or 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 * * ----------------------------------------------------------- */ diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index ef1cda5..220a263 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -9,6 +9,7 @@ See the file COPYING.LIB */ +#include #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);