diff options
author | Bernd Schubert <bschubert@ddn.com> | 2025-05-18 00:24:07 +0200 |
---|---|---|
committer | Bernd Schubert <bernd@bsbernd.com> | 2025-05-20 18:14:44 +0200 |
commit | baadab0492a495fda98216b351976d2e5d6d0866 (patch) | |
tree | 61017d2976439c6b7453b402aad5ecd3816b72ef /test | |
parent | eadd6a5454373c7c404463c81be652275da5e07b (diff) | |
download | libfuse-baadab0492a495fda98216b351976d2e5d6d0866.tar.gz |
conn->want conversion: Fix fuse_apply_conn_info_opts()
fuse_apply_conn_info_opts() was applying to 'want_ext',
which would cause conflicts with 'want' if the application
applied its own flags to 'conn->want'.
Solution is:
- to move fuse_{set,unset,get}_feature_flag and
convert_to_conn_want_ext() to fuse_lowlevel.c and
to define them as part of the public API, although
convert_to_conn_want_ext() should not be used - it is
currently needed to be a public function due as it needs
to be defined for the tests.
Related to https://github.com/libfuse/libfuse/issues/1171 and
https://github.com/libfuse/libfuse/pull/1172.
Closes: https://github.com/libfuse/libfuse/issues/1171
Signed-off-by: Bernd Schubert <bschubert@ddn.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/test_want_conversion.c | 97 |
1 files changed, 57 insertions, 40 deletions
diff --git a/test/test_want_conversion.c b/test/test_want_conversion.c index bee23cc..db731ed 100644 --- a/test/test_want_conversion.c +++ b/test/test_want_conversion.c @@ -1,16 +1,22 @@ -#include "util.h" #define FUSE_USE_VERSION FUSE_MAKE_VERSION(3, 17) +#include "util.h" #include "fuse_i.h" +#include "fuse_lowlevel.h" #include <stdio.h> #include <assert.h> #include <inttypes.h> #include <stdbool.h> +#include <err.h> static void print_conn_info(const char *prefix, struct fuse_conn_info *conn) { - printf("%s: want=0x%" PRIx32 " want_ext=0x%" PRIx64 "\n", prefix, - conn->want, conn->want_ext); + struct fuse_session *se = container_of(conn, struct fuse_session, conn); + + printf("%s: want=0x%" PRIx32 " want_ext=0x%" PRIx64 + " want_default=0x%" PRIx32 " want_ext_default=0x%" PRIx64 "\n", + prefix, conn->want, conn->want_ext, se->conn_want, + se->conn_want_ext); } static void application_init_old_style(struct fuse_conn_info *conn) @@ -18,33 +24,31 @@ static void application_init_old_style(struct fuse_conn_info *conn) /* Simulate application init the old style */ conn->want |= FUSE_CAP_ASYNC_READ; conn->want &= ~FUSE_CAP_SPLICE_READ; + + /* + * Also use new style API, as that might happen through + * fuse_apply_conn_info_opts() + */ + fuse_set_feature_flag(conn, FUSE_CAP_IOCTL_DIR); } static void application_init_new_style(struct fuse_conn_info *conn) { /* Simulate application init the new style */ fuse_set_feature_flag(conn, FUSE_CAP_ASYNC_READ); + fuse_set_feature_flag(conn, FUSE_CAP_IOCTL_DIR); fuse_unset_feature_flag(conn, FUSE_CAP_SPLICE_READ); } static void test_fuse_fs_init(struct fuse_conn_info *conn, bool new_style) { - uint64_t want_ext_default = conn->want_ext; - uint32_t want_default = fuse_lower_32_bits(conn->want_ext); - int rc; - /* High-level init */ fuse_set_feature_flag(conn, FUSE_CAP_EXPORT_SUPPORT); - conn->want = want_default; - if (new_style) application_init_new_style(conn); else application_init_old_style(conn); - - rc = convert_to_conn_want_ext(conn, want_ext_default, want_default); - assert(rc == 0); } static void test_do_init(struct fuse_conn_info *conn, bool new_style) @@ -53,49 +57,71 @@ static void test_do_init(struct fuse_conn_info *conn, bool new_style) conn->capable_ext = FUSE_CAP_SPLICE_READ | FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE | FUSE_CAP_POSIX_LOCKS | FUSE_CAP_FLOCK_LOCKS | FUSE_CAP_EXPORT_SUPPORT | - FUSE_CAP_ASYNC_READ; + FUSE_CAP_ASYNC_READ | FUSE_CAP_IOCTL_DIR; conn->capable = fuse_lower_32_bits(conn->capable_ext); - conn->want_ext = conn->capable_ext; + + fuse_set_feature_flag(conn, FUSE_CAP_SPLICE_READ | + FUSE_CAP_SPLICE_WRITE | + FUSE_CAP_SPLICE_MOVE); print_conn_info("Initial state", conn); - uint64_t want_ext_default = conn->want_ext; - uint32_t want_default = fuse_lower_32_bits(conn->want_ext); int rc; - conn->want = want_default; - conn->capable = fuse_lower_32_bits(conn->capable_ext); - test_fuse_fs_init(conn, new_style); + print_conn_info("After init", conn); - rc = convert_to_conn_want_ext(conn, want_ext_default, want_default); + rc = fuse_convert_to_conn_want_ext(conn); assert(rc == 0); /* Verify all expected flags are set */ assert(!(conn->want_ext & FUSE_CAP_SPLICE_READ)); assert(conn->want_ext & FUSE_CAP_SPLICE_WRITE); assert(conn->want_ext & FUSE_CAP_SPLICE_MOVE); - assert(conn->want_ext & FUSE_CAP_POSIX_LOCKS); - assert(conn->want_ext & FUSE_CAP_FLOCK_LOCKS); assert(conn->want_ext & FUSE_CAP_EXPORT_SUPPORT); assert(conn->want_ext & FUSE_CAP_ASYNC_READ); + assert(conn->want_ext & FUSE_CAP_IOCTL_DIR); + /* Verify no other flags are set */ assert(conn->want_ext == (FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE | - FUSE_CAP_POSIX_LOCKS | FUSE_CAP_FLOCK_LOCKS | - FUSE_CAP_EXPORT_SUPPORT | FUSE_CAP_ASYNC_READ)); + FUSE_CAP_EXPORT_SUPPORT | FUSE_CAP_ASYNC_READ | + FUSE_CAP_IOCTL_DIR)); print_conn_info("After init", conn); } static void test_want_conversion_basic(void) { - struct fuse_conn_info conn = { 0 }; + const struct fuse_lowlevel_ops ops = { 0 }; + struct fuse_args args = FUSE_ARGS_INIT(0, NULL); + struct fuse_session *se; + struct fuse_conn_info *conn; + + /* Add the program name to arg[0] */ + if (fuse_opt_add_arg(&args, "test_signals")) { + fprintf(stderr, "Failed to add argument\n"); + errx(1, "Failed to add argument"); + } + + + se = fuse_session_new(&args, &ops, sizeof(ops), NULL); + assert(se); + conn = &se->conn; + printf("\nTesting basic want conversion, old style:\n"); + test_do_init(conn, false); + fuse_session_destroy(se); + + se = fuse_session_new(&args, &ops, sizeof(ops), NULL); + assert(se); + conn = &se->conn; + printf("\nTesting basic want conversion, new style:\n"); + test_do_init(conn, true); + print_conn_info("After init", conn); + fuse_session_destroy(se); + + fuse_opt_free_args(&args); - printf("\nTesting basic want conversion:\n"); - test_do_init(&conn, false); - test_do_init(&conn, true); - print_conn_info("After init", &conn); } static void test_want_conversion_conflict(void) @@ -115,16 +141,11 @@ static void test_want_conversion_conflict(void) conn.want = fuse_lower_32_bits(conn.want_ext); print_conn_info("Test conflict initial", &conn); - /* Initialize default values like in basic test */ - uint64_t want_ext_default_ll = conn.want_ext; - uint32_t want_default_ll = fuse_lower_32_bits(want_ext_default_ll); - /* Simulate application init modifying capabilities */ conn.want_ext |= FUSE_CAP_ATOMIC_O_TRUNC; /* Add new capability */ conn.want &= ~FUSE_CAP_SPLICE_READ; /* Remove a capability */ - rc = convert_to_conn_want_ext(&conn, want_ext_default_ll, - want_default_ll); + rc = fuse_convert_to_conn_want_ext(&conn); assert(rc == -EINVAL); print_conn_info("Test conflict after", &conn); @@ -143,11 +164,7 @@ static void test_want_conversion_high_bits(void) conn.want = fuse_lower_32_bits(conn.want_ext); print_conn_info("Test high bits initial", &conn); - uint64_t want_ext_default_ll = conn.want_ext; - uint32_t want_default_ll = fuse_lower_32_bits(want_ext_default_ll); - - rc = convert_to_conn_want_ext(&conn, want_ext_default_ll, - want_default_ll); + rc = fuse_convert_to_conn_want_ext(&conn); assert(rc == 0); assert(conn.want_ext == ((1ULL << 33) | FUSE_CAP_ASYNC_READ)); print_conn_info("Test high bits after", &conn); |