aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlessio Balsini <balsini@google.com>2022-01-22 12:51:41 +0000
committerAlessio Balsini <balsini@google.com>2022-05-23 10:37:59 +0100
commitab9271b86f27e13ee340ad4d4bddce836657d7c2 (patch)
tree93851dd88c0eb533cd0995c5d8ee49ed4e24b283
parent3ec30a861ca92e55bbad9b709ab6f22636a226f0 (diff)
downloadlibfuse-ab9271b86f27e13ee340ad4d4bddce836657d7c2.tar.gz
Extend initialization flags and FUSE_PASSTHROUGH to 64 bits
With the latest kernel version the FUSE_PASSTHROUGH flag now conflicts with another flag. As the flag bits in the original "flags" field are all covered, the developer allocated another "flags2" field in the userspace <-> kernelspace communication. While FUSE_PASSTHROUGH is kept as the last bit of either field, it's userspace that needs to decide if it should be the last bit of "flags" or "flags2" based on the FUSE version. Test: launch_cvd (both android-mainline and android13-5.10) \ `logcat FuseDaemon:V \*:S` shows no FUSE passthrough errors Bug: 215310351 Signed-off-by: Alessio Balsini <balsini@google.com> Change-Id: Ib35e5e162b57a49fde1c36154adafb51172fc2bd
-rw-r--r--include/fuse_common.h6
-rw-r--r--lib/fuse_lowlevel.c22
2 files changed, 21 insertions, 7 deletions
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 3f836d7..d6fa3e2 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -409,7 +409,7 @@ struct fuse_loop_config {
*
* This feature is disabled by default.
*/
-#define FUSE_CAP_PASSTHROUGH (1 << 31)
+#define FUSE_CAP_PASSTHROUGH (1LL << 63)
/**
* Ioctl flags
@@ -473,7 +473,7 @@ struct fuse_conn_info {
/**
* Capability flags that the kernel supports (read-only)
*/
- unsigned capable;
+ uint64_t capable;
/**
* Capability flags that the filesystem wants to enable.
@@ -481,7 +481,7 @@ struct fuse_conn_info {
* libfuse attempts to initialize this field with
* reasonable default values before calling the init() handler.
*/
- unsigned want;
+ uint64_t want;
/**
* Maximum number of pending "background" requests. A
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index aee22b4..2ede5f3 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -2013,6 +2013,7 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
struct fuse_session *se = req->se;
size_t bufsize = se->bufsize;
size_t outargsize = sizeof(outarg);
+ int extended_flags;
(void) nodeid;
if (se->debug) {
@@ -2032,6 +2033,10 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outarg.major = FUSE_KERNEL_VERSION;
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
+ extended_flags = arg->major > 7 || (arg->major == 7 && arg->minor >= 36);
+ fuse_log(FUSE_LOG_DEBUG, "fuse: protocol version: %u.%u, extended flags: %d\n",
+ arg->major, arg->minor, extended_flags);
+
if (arg->major < 7) {
fuse_log(FUSE_LOG_ERR, "fuse: unsupported protocol version: %u.%u\n",
arg->major, arg->minor);
@@ -2092,8 +2097,13 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
bufsize = max_bufsize;
}
}
- if (arg->flags & FUSE_PASSTHROUGH)
- se->conn.capable |= FUSE_PASSTHROUGH;
+ if (extended_flags) {
+ if (arg->flags2 & (1 << 31))
+ se->conn.capable |= FUSE_CAP_PASSTHROUGH;
+ } else {
+ if (arg->flags & (1 << 31))
+ se->conn.capable |= FUSE_CAP_PASSTHROUGH;
+ }
} else {
se->conn.max_readahead = 0;
}
@@ -2206,8 +2216,12 @@ void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outarg.flags |= FUSE_WRITEBACK_CACHE;
if (se->conn.want & FUSE_CAP_POSIX_ACL)
outarg.flags |= FUSE_POSIX_ACL;
- if (se->conn.want & FUSE_CAP_PASSTHROUGH)
- outarg.flags |= FUSE_PASSTHROUGH;
+ if (se->conn.want & FUSE_CAP_PASSTHROUGH) {
+ if (extended_flags)
+ outarg.flags2 |= (1 << 31);
+ else
+ outarg.flags |= (1 << 31);
+ }
if (se->conn.want & FUSE_CAP_CACHE_SYMLINKS)
outarg.flags |= FUSE_CACHE_SYMLINKS;
if (se->conn.want & FUSE_CAP_EXPLICIT_INVAL_DATA)