Add fuse_set_feature_flag() / fuse_unset_feature_flag
authorBernd Schubert <bschubert@ddn.com>
Thu, 19 Sep 2024 13:03:55 +0000 (15:03 +0200)
committerBernd Schubert <bernd.schubert@fastmail.fm>
Wed, 13 Nov 2024 15:43:59 +0000 (16:43 +0100)
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.

example/passthrough_hp.cc
include/fuse_common.h
lib/fuse_lowlevel.c

index bfaada5c64c442a321f54fcfd49faf8eccd4bd29..1f6647fc69773918b13e8ca05781b05ceac72207 100644 (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;
index 38bac4e2c239b1b5abd5369d77b3f1e19b8b7e71..1abac5af9cf675d3bcb6e704dd00075e13ad8108 100644 (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                                        *
  * ----------------------------------------------------------- */
index ef1cda5606f66a075ec8fa68e609f217239bbdae..220a2639519094eb5f8288b0d821ee3a3ce973ba 100644 (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);