diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:35:19 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-15 01:35:19 +0000 |
commit | 42c98dfb84b501fb59c37c1ebd5e3c1f22337f39 (patch) | |
tree | 3e5075efec3f16265f9fe0bdf93d9bb0cdce7107 | |
parent | 3826441535b4be3dea5e3974288e80cdb6f1fdea (diff) | |
parent | 7fdddf2190c5c3cc7c7d4ffd103199b4803fa028 (diff) | |
download | libfuse-42c98dfb84b501fb59c37c1ebd5e3c1f22337f39.tar.gz |
Snap for 7550844 from 7fdddf2190c5c3cc7c7d4ffd103199b4803fa028 to mainline-tethering-releaseandroid-mainline-12.0.0_r95android-mainline-12.0.0_r82android-mainline-12.0.0_r66android-mainline-12.0.0_r53android-mainline-12.0.0_r38android-mainline-12.0.0_r18android-mainline-12.0.0_r125android-mainline-12.0.0_r110aml_tet_311811050android12-mainline-tethering-release
Change-Id: I118e1239e8358a35f624c50729fdeb048d3c6d77
-rw-r--r-- | Android.bp | 41 | ||||
-rw-r--r-- | OWNERS | 1 | ||||
-rw-r--r-- | include/fuse_common.h | 17 | ||||
-rw-r--r-- | include/fuse_kernel.h | 15 | ||||
-rw-r--r-- | include/fuse_lowlevel.h | 2 | ||||
-rw-r--r-- | lib/fuse_lowlevel.c | 77 | ||||
-rw-r--r-- | lib/fuse_versionscript | 1 |
7 files changed, 152 insertions, 2 deletions
@@ -1,3 +1,44 @@ +package { + default_applicable_licenses: ["external_libfuse_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// +// large-scale-change included anything that looked like it might be a license +// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc. +// +// Please consider removing redundant or irrelevant files from 'license_text:'. +// See: http://go/android-license-faq +license { + name: "external_libfuse_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-BSD", + "SPDX-license-identifier-GPL", + "SPDX-license-identifier-GPL-2.0", + "SPDX-license-identifier-LGPL", + "SPDX-license-identifier-LGPL-2.0", + "SPDX-license-identifier-LGPL-2.1", + "SPDX-license-identifier-LGPL-3.0", + ], + license_text: [ + "LGPL2.txt", + "LICENSE", + ], +} + cc_defaults { name: "libfuse_default_flags", local_include_dirs: ["include/", "lib/"], @@ -0,0 +1 @@ +balsini@google.com diff --git a/include/fuse_common.h b/include/fuse_common.h index 2d686b2..7ac28d7 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -92,6 +92,11 @@ struct fuse_file_info { * same file handle. */ uint64_t fh; + /** Passthrough file handle id. May be filled in by filesystem in + * create and open. It is used to create a passthrough connection + * between FUSE file and lower file system file. */ + uint32_t passthrough_fh; + /** Lock owner id. Available in locking operations and flush */ uint64_t lock_owner; @@ -359,6 +364,18 @@ struct fuse_loop_config { #define FUSE_CAP_NO_OPENDIR_SUPPORT (1 << 24) /** + * Indicates support for passthrough mode access for read/write operations. + * + * If this flag is set in the `capable` field of the `fuse_conn_info` + * structure, then the FUSE kernel module supports redirecting read/write + * operations to the lower file system instead of letting them to be handled + * by the FUSE daemon. + * + * This feature is disabled by default. + */ +#define FUSE_CAP_PASSTHROUGH (1 << 31) + +/** * Ioctl flags * * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h index 8a45f42..bd8794e 100644 --- a/include/fuse_kernel.h +++ b/include/fuse_kernel.h @@ -301,6 +301,7 @@ struct fuse_file_lock { #define FUSE_CACHE_SYMLINKS (1 << 23) #define FUSE_NO_OPENDIR_SUPPORT (1 << 24) #define FUSE_EXPLICIT_INVAL_DATA (1 << 25) +#define FUSE_PASSTHROUGH (1 << 31) /** * CUSE INIT request/reply flags @@ -547,7 +548,7 @@ struct fuse_create_in { struct fuse_open_out { uint64_t fh; uint32_t open_flags; - uint32_t padding; + uint32_t passthrough_fh; }; struct fuse_release_in { @@ -574,6 +575,13 @@ struct fuse_read_in { uint32_t padding; }; +struct fuse_passthrough_out_v0 { + uint32_t fd; + /* For future implementation */ + uint32_t len; + void * vec; +}; + #define FUSE_COMPAT_WRITE_IN_SIZE 24 struct fuse_write_in { @@ -825,7 +833,10 @@ struct fuse_notify_retrieve_in { }; /* Device ioctls: */ -#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) +#define FUSE_DEV_IOC_CLONE _IOR(229, 0, uint32_t) +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V0 _IOW(229, 1, struct fuse_passthrough_out_v0) +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V1 _IOW(229, 127, struct fuse_passthrough_out_v0) +#define FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2 _IOW(229, 126, uint32_t) struct fuse_lseek_in { uint64_t fh; diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index e81c282..e916112 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1349,6 +1349,8 @@ int fuse_reply_attr(fuse_req_t req, const struct stat *attr, */ int fuse_reply_readlink(fuse_req_t req, const char *link); +int fuse_passthrough_enable(fuse_req_t req, unsigned int fd); + /** * Reply with the canonical path for inotify * diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index fc76b7c..a4a4df0 100644 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -27,6 +27,7 @@ #include <errno.h> #include <assert.h> #include <sys/file.h> +#include <sys/ioctl.h> #ifndef F_LINUX_SPECIFIC_BASE #define F_LINUX_SPECIFIC_BASE 1024 @@ -388,6 +389,7 @@ static void fill_open(struct fuse_open_out *arg, const struct fuse_file_info *f) { arg->fh = f->fh; + arg->passthrough_fh = f->passthrough_fh; if (f->direct_io) arg->open_flags |= FOPEN_DIRECT_IO; if (f->keep_cache) @@ -457,6 +459,77 @@ int fuse_reply_canonical_path(fuse_req_t req, const char *path) return send_reply_ok(req, path, strlen(path) + 1); } +enum { + FUSE_PASSTHROUGH_API_UNAVAILABLE, + FUSE_PASSTHROUGH_API_V0, + FUSE_PASSTHROUGH_API_V1, + FUSE_PASSTHROUGH_API_V2, + FUSE_PASSTHROUGH_API_STABLE, +}; + +/* + * Requests the FUSE passthrough feature to be enabled on a specific file + * through the passed fd. + * This function returns an identifier that must be used as passthrough_fh + * when the open/create_open request reply is sent back to /dev/fuse. + * As for the current FUSE passthrough implementation, passthrough_fh values + * are only valid if > 0, so in case the FUSE passthrough open ioctl returns + * a value <= 0, this must be considered an error and is returned as-is by + * this function. + */ +int fuse_passthrough_enable(fuse_req_t req, unsigned int fd) { + static sig_atomic_t passthrough_version = FUSE_PASSTHROUGH_API_STABLE; + int ret = 0; /* values <= 0 represent errors in FUSE passthrough */ + + /* + * The interface of FUSE passthrough is still unstable in the kernel, + * so the following solution is to search for the most updated API + * version and, if not found, fall back to an older one. + * This happens when ioctl() returns -1 and errno is set to ENOTTY, + * an error code that corresponds to the lack of a specific ioctl. + */ + switch (passthrough_version) { + case FUSE_PASSTHROUGH_API_STABLE: + /* There is not a stable API yet */ + passthrough_version = FUSE_PASSTHROUGH_API_V2; + case FUSE_PASSTHROUGH_API_V2: { + ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V2, &fd); + if (ret == -1 && errno == ENOTTY) + passthrough_version = FUSE_PASSTHROUGH_API_V1; + else + break; + } + case FUSE_PASSTHROUGH_API_V1: { + struct fuse_passthrough_out_v0 out = {}; + out.fd = fd; + + ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V1, &out); + if (ret == -1 && errno == ENOTTY) + passthrough_version = FUSE_PASSTHROUGH_API_V0; + else + break; + } + case FUSE_PASSTHROUGH_API_V0: { + struct fuse_passthrough_out_v0 out = {}; + out.fd = fd; + + ret = ioctl(req->se->fd, FUSE_DEV_IOC_PASSTHROUGH_OPEN_V0, &out); + if (ret == -1 && errno == ENOTTY) + passthrough_version = FUSE_PASSTHROUGH_API_UNAVAILABLE; + else + break; + } + default: + fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable no valid API\n"); + return -ENOTTY; + } + + if (ret <= 0) + fuse_log(FUSE_LOG_ERR, "fuse: passthrough_enable: %s\n", strerror(errno)); + + return ret; +} + int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *f) { struct fuse_open_out arg; @@ -1990,6 +2063,8 @@ static 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; } else { se->conn.max_readahead = 0; } @@ -2102,6 +2177,8 @@ static 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; outarg.max_readahead = se->conn.max_readahead; outarg.max_write = se->conn.max_write; if (se->conn.proto_minor >= 13) { diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index 4c075a3..b01699a 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -163,6 +163,7 @@ FUSE_3.7 { global: fuse_set_log_func; fuse_log; + fuse_passthrough_enable; fuse_reply_canonical_path; } FUSE_3.3; |