* [PATCH] selftests: Add functional test for the abort file in fusectl
@ 2025-05-15 7:34 Chen Linxuan
2025-05-15 7:44 ` Chen Linxuan
2025-05-15 10:26 ` Amir Goldstein
0 siblings, 2 replies; 5+ messages in thread
From: Chen Linxuan @ 2025-05-15 7:34 UTC (permalink / raw)
To: Shuah Khan, Miklos Szeredi
Cc: zhanjun, niecheng1, wentao, Chen Linxuan, Amir Goldstein,
linux-kernel, linux-kselftest, linux-fsdevel
This patch add a simple functional test for the "about" file
in fusectlfs (/sys/fs/fuse/connections/ID/about).
A simple fuse daemon is added for testing.
Related discussion can be found in the link below.
Link: https://lore.kernel.org/all/CAOQ4uxjKFXOKQxPpxtS6G_nR0tpw95w0GiO68UcWg_OBhmSY=Q@mail.gmail.com/
Cc: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Chen Linxuan <chenlinxuan@uniontech.com>
---
MAINTAINERS | 1 +
tools/testing/selftests/Makefile | 1 +
.../selftests/filesystems/fusectl/.gitignore | 3 +
.../selftests/filesystems/fusectl/Makefile | 21 +++
.../selftests/filesystems/fusectl/fuse_mnt.c | 146 ++++++++++++++++++
.../filesystems/fusectl/fusectl_test.c | 115 ++++++++++++++
6 files changed, 287 insertions(+)
create mode 100644 tools/testing/selftests/filesystems/fusectl/.gitignore
create mode 100644 tools/testing/selftests/filesystems/fusectl/Makefile
create mode 100644 tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
create mode 100644 tools/testing/selftests/filesystems/fusectl/fusectl_test.c
diff --git a/MAINTAINERS b/MAINTAINERS
index f21f1dabb5fe1..efc6c89113b95 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9740,6 +9740,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git
F: Documentation/filesystems/fuse.rst
F: fs/fuse/
F: include/uapi/linux/fuse.h
+F: tools/testing/selftests/filesystems/fusectl
FUTEX SUBSYSTEM
M: Thomas Gleixner <tglx@linutronix.de>
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 80fb84fa3cfcb..a9bfefa961889 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -36,6 +36,7 @@ TARGETS += filesystems/fat
TARGETS += filesystems/overlayfs
TARGETS += filesystems/statmount
TARGETS += filesystems/mount-notify
+TARGETS += filesystems/fusectl
TARGETS += firmware
TARGETS += fpu
TARGETS += ftrace
diff --git a/tools/testing/selftests/filesystems/fusectl/.gitignore b/tools/testing/selftests/filesystems/fusectl/.gitignore
new file mode 100644
index 0000000000000..3e72e742d08e8
--- /dev/null
+++ b/tools/testing/selftests/filesystems/fusectl/.gitignore
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+fuse_mnt
+fusectl_test
diff --git a/tools/testing/selftests/filesystems/fusectl/Makefile b/tools/testing/selftests/filesystems/fusectl/Makefile
new file mode 100644
index 0000000000000..612aad69a93aa
--- /dev/null
+++ b/tools/testing/selftests/filesystems/fusectl/Makefile
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
+
+TEST_GEN_PROGS := fusectl_test
+TEST_GEN_FILES := fuse_mnt
+
+include ../../lib.mk
+
+VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null)
+ifeq ($(VAR_CFLAGS),)
+VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
+endif
+
+VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
+ifeq ($(VAR_LDLIBS),)
+VAR_LDLIBS := -lfuse -pthread
+endif
+
+$(OUTPUT)/fuse_mnt: CFLAGS += $(VAR_CFLAGS)
+$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
diff --git a/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c b/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
new file mode 100644
index 0000000000000..d12b17f30fadc
--- /dev/null
+++ b/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * fusectl test file-system
+ * Creates a simple FUSE filesystem with a single read-write file (/test)
+ */
+
+#define FUSE_USE_VERSION 26
+
+#include <fuse.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+static char *content;
+static size_t content_size = 0;
+static const char test_path[] = "/test";
+
+static int test_getattr(const char *path, struct stat *st)
+{
+ memset(st, 0, sizeof(*st));
+
+ if (!strcmp(path, "/")) {
+ st->st_mode = S_IFDIR | 0755;
+ st->st_nlink = 2;
+ return 0;
+ }
+
+ if (!strcmp(path, test_path)) {
+ st->st_mode = S_IFREG | 0664;
+ st->st_nlink = 1;
+ st->st_size = content_size;
+ return 0;
+ }
+
+ return -ENOENT;
+}
+
+static int test_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi)
+{
+ if (strcmp(path, "/"))
+ return -ENOENT;
+
+ filler(buf, ".", NULL, 0);
+ filler(buf, "..", NULL, 0);
+ filler(buf, test_path + 1, NULL, 0);
+
+ return 0;
+}
+
+static int test_open(const char *path, struct fuse_file_info *fi)
+{
+ if (strcmp(path, test_path))
+ return -ENOENT;
+
+ return 0;
+}
+
+static int test_read(const char *path, char *buf, size_t size, off_t offset,
+ struct fuse_file_info *fi)
+{
+ if (strcmp(path, test_path) != 0)
+ return -ENOENT;
+
+ if (!content || content_size == 0)
+ return 0;
+
+ if (offset >= content_size)
+ return 0;
+
+ if (offset + size > content_size)
+ size = content_size - offset;
+
+ memcpy(buf, content + offset, size);
+
+ return size;
+}
+
+static int test_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+{
+ size_t new_size;
+
+ if (strcmp(path, test_path) != 0)
+ return -ENOENT;
+
+ if(offset > content_size)
+ return -EINVAL;
+
+ new_size = MAX(offset + size, content_size);
+
+ if (new_size > content_size)
+ content = realloc(content, new_size);
+
+ content_size = new_size;
+
+ if (!content)
+ return -ENOMEM;
+
+ memcpy(content + offset, buf, size);
+
+ return size;
+}
+
+static int test_truncate(const char *path, off_t size)
+{
+ if (strcmp(path, test_path) != 0)
+ return -ENOENT;
+
+ if (size == 0) {
+ free(content);
+ content = NULL;
+ content_size = 0;
+ return 0;
+ }
+
+ content = realloc(content, size);
+
+ if (!content)
+ return -ENOMEM;
+
+ if (size > content_size)
+ memset(content + content_size, 0, size - content_size);
+
+ content_size = size;
+ return 0;
+}
+
+static struct fuse_operations memfd_ops = {
+ .getattr = test_getattr,
+ .readdir = test_readdir,
+ .open = test_open,
+ .read = test_read,
+ .write = test_write,
+ .truncate = test_truncate,
+};
+
+int main(int argc, char *argv[])
+{
+ return fuse_main(argc, argv, &memfd_ops, NULL);
+}
diff --git a/tools/testing/selftests/filesystems/fusectl/fusectl_test.c b/tools/testing/selftests/filesystems/fusectl/fusectl_test.c
new file mode 100644
index 0000000000000..8ff130ae43122
--- /dev/null
+++ b/tools/testing/selftests/filesystems/fusectl/fusectl_test.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (c) 2025 Chen Linxuan <chenlinxuan@uniontech.com>
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <linux/limits.h>
+
+#include "../../kselftest_harness.h"
+
+#define FUSECTL_MOUNTPOINT "/sys/fs/fuse/connections"
+#define FUSE_MOUNTPOINT "/tmp/fuse_mnt_XXXXXX"
+#define FUSE_DEVICE "/dev/fuse"
+#define FUSECTL_TEST_VALUE "1"
+
+FIXTURE(fusectl){
+ char fuse_mountpoint[sizeof(FUSE_MOUNTPOINT)];
+ int connection;
+};
+
+FIXTURE_SETUP(fusectl)
+{
+ const char *fuse_mnt_prog = "./fuse_mnt";
+ int status, pid;
+ struct stat statbuf;
+
+ strcpy(self->fuse_mountpoint, FUSE_MOUNTPOINT);
+
+ if (!mkdtemp(self->fuse_mountpoint))
+ SKIP(return,
+ "Failed to create FUSE mountpoint %s",
+ strerror(errno));
+
+ if (access(FUSECTL_MOUNTPOINT, F_OK))
+ SKIP(return,
+ "FUSE control filesystem not mounted");
+
+ pid = fork();
+ if (pid < 0)
+ SKIP(return,
+ "Failed to fork FUSE daemon process: %s",
+ strerror(errno));
+
+ if (pid == 0) {
+ execlp(fuse_mnt_prog, fuse_mnt_prog, self->fuse_mountpoint, NULL);
+ exit(errno);
+ }
+
+ waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ SKIP(return,
+ "Failed to start FUSE daemon %s",
+ strerror(WEXITSTATUS(status)));
+ }
+
+ if (stat(self->fuse_mountpoint, &statbuf))
+ SKIP(return,
+ "Failed to stat FUSE mountpoint %s",
+ strerror(errno));
+
+ self->connection = statbuf.st_dev;
+}
+
+FIXTURE_TEARDOWN(fusectl)
+{
+ umount(self->fuse_mountpoint);
+ rmdir(self->fuse_mountpoint);
+}
+
+TEST_F(fusectl, abort)
+{
+ char path_buf[PATH_MAX];
+ int abort_fd, test_fd, ret;
+
+ sprintf(path_buf, "/sys/fs/fuse/connections/%d/abort", self->connection);
+
+ ASSERT_EQ(0, access(path_buf, F_OK));
+
+ abort_fd = open(path_buf, O_WRONLY);
+ ASSERT_GE(abort_fd, 0);
+
+ sprintf(path_buf, "%s/test", self->fuse_mountpoint);
+
+ test_fd = open(path_buf, O_RDWR);
+ ASSERT_GE(test_fd, 0);
+
+ ret = read(test_fd, path_buf, sizeof(path_buf));
+ ASSERT_EQ(ret, 0);
+
+ ret = write(test_fd, "test", sizeof("test"));
+ ASSERT_EQ(ret, sizeof("test"));
+
+ ret = lseek(test_fd, 0, SEEK_SET);
+ ASSERT_GE(ret, 0);
+
+ ret = write(abort_fd, FUSECTL_TEST_VALUE, sizeof(FUSECTL_TEST_VALUE));
+ ASSERT_GT(ret, 0);
+
+ close(abort_fd);
+
+ ret = read(test_fd, path_buf, sizeof(path_buf));
+ ASSERT_LT(ret, 0);
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] selftests: Add functional test for the abort file in fusectl
2025-05-15 7:34 [PATCH] selftests: Add functional test for the abort file in fusectl Chen Linxuan
@ 2025-05-15 7:44 ` Chen Linxuan
2025-05-15 10:26 ` Amir Goldstein
1 sibling, 0 replies; 5+ messages in thread
From: Chen Linxuan @ 2025-05-15 7:44 UTC (permalink / raw)
To: Chen Linxuan
Cc: Shuah Khan, Miklos Szeredi, zhanjun, niecheng1, wentao,
Amir Goldstein, linux-kernel, linux-kselftest, linux-fsdevel
On Thu, May 15, 2025 at 3:35 PM Chen Linxuan <chenlinxuan@uniontech.com> wrote:
> This patch add a simple functional test for the "about" file
Sorry for the typo, it should be "abort".
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] selftests: Add functional test for the abort file in fusectl
2025-05-15 7:34 [PATCH] selftests: Add functional test for the abort file in fusectl Chen Linxuan
2025-05-15 7:44 ` Chen Linxuan
@ 2025-05-15 10:26 ` Amir Goldstein
2025-05-19 5:57 ` Chen Linxuan
1 sibling, 1 reply; 5+ messages in thread
From: Amir Goldstein @ 2025-05-15 10:26 UTC (permalink / raw)
To: Chen Linxuan
Cc: Shuah Khan, Miklos Szeredi, zhanjun, niecheng1, wentao,
linux-kernel, linux-kselftest, linux-fsdevel
On Thu, May 15, 2025 at 9:35 AM Chen Linxuan <chenlinxuan@uniontech.com> wrote:
>
> This patch add a simple functional test for the "about" file
> in fusectlfs (/sys/fs/fuse/connections/ID/about).
>
> A simple fuse daemon is added for testing.
>
> Related discussion can be found in the link below.
>
> Link: https://lore.kernel.org/all/CAOQ4uxjKFXOKQxPpxtS6G_nR0tpw95w0GiO68UcWg_OBhmSY=Q@mail.gmail.com/
> Cc: Amir Goldstein <amir73il@gmail.com>
> Signed-off-by: Chen Linxuan <chenlinxuan@uniontech.com>
> ---
> MAINTAINERS | 1 +
> tools/testing/selftests/Makefile | 1 +
> .../selftests/filesystems/fusectl/.gitignore | 3 +
> .../selftests/filesystems/fusectl/Makefile | 21 +++
> .../selftests/filesystems/fusectl/fuse_mnt.c | 146 ++++++++++++++++++
> .../filesystems/fusectl/fusectl_test.c | 115 ++++++++++++++
> 6 files changed, 287 insertions(+)
> create mode 100644 tools/testing/selftests/filesystems/fusectl/.gitignore
> create mode 100644 tools/testing/selftests/filesystems/fusectl/Makefile
> create mode 100644 tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
> create mode 100644 tools/testing/selftests/filesystems/fusectl/fusectl_test.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f21f1dabb5fe1..efc6c89113b95 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -9740,6 +9740,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git
> F: Documentation/filesystems/fuse.rst
> F: fs/fuse/
> F: include/uapi/linux/fuse.h
> +F: tools/testing/selftests/filesystems/fusectl
>
> FUTEX SUBSYSTEM
> M: Thomas Gleixner <tglx@linutronix.de>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index 80fb84fa3cfcb..a9bfefa961889 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -36,6 +36,7 @@ TARGETS += filesystems/fat
> TARGETS += filesystems/overlayfs
> TARGETS += filesystems/statmount
> TARGETS += filesystems/mount-notify
> +TARGETS += filesystems/fusectl
> TARGETS += firmware
> TARGETS += fpu
> TARGETS += ftrace
> diff --git a/tools/testing/selftests/filesystems/fusectl/.gitignore b/tools/testing/selftests/filesystems/fusectl/.gitignore
> new file mode 100644
> index 0000000000000..3e72e742d08e8
> --- /dev/null
> +++ b/tools/testing/selftests/filesystems/fusectl/.gitignore
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +fuse_mnt
> +fusectl_test
> diff --git a/tools/testing/selftests/filesystems/fusectl/Makefile b/tools/testing/selftests/filesystems/fusectl/Makefile
> new file mode 100644
> index 0000000000000..612aad69a93aa
> --- /dev/null
> +++ b/tools/testing/selftests/filesystems/fusectl/Makefile
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +
> +CFLAGS += -Wall -O2 -g $(KHDR_INCLUDES)
> +
> +TEST_GEN_PROGS := fusectl_test
> +TEST_GEN_FILES := fuse_mnt
> +
> +include ../../lib.mk
> +
> +VAR_CFLAGS := $(shell pkg-config fuse --cflags 2>/dev/null)
> +ifeq ($(VAR_CFLAGS),)
> +VAR_CFLAGS := -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse
> +endif
> +
> +VAR_LDLIBS := $(shell pkg-config fuse --libs 2>/dev/null)
> +ifeq ($(VAR_LDLIBS),)
> +VAR_LDLIBS := -lfuse -pthread
> +endif
> +
> +$(OUTPUT)/fuse_mnt: CFLAGS += $(VAR_CFLAGS)
> +$(OUTPUT)/fuse_mnt: LDLIBS += $(VAR_LDLIBS)
> diff --git a/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c b/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
> new file mode 100644
> index 0000000000000..d12b17f30fadc
> --- /dev/null
> +++ b/tools/testing/selftests/filesystems/fusectl/fuse_mnt.c
> @@ -0,0 +1,146 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * fusectl test file-system
> + * Creates a simple FUSE filesystem with a single read-write file (/test)
> + */
> +
> +#define FUSE_USE_VERSION 26
> +
> +#include <fuse.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +
> +#define MAX(a, b) ((a) > (b) ? (a) : (b))
> +
> +static char *content;
> +static size_t content_size = 0;
> +static const char test_path[] = "/test";
> +
> +static int test_getattr(const char *path, struct stat *st)
> +{
> + memset(st, 0, sizeof(*st));
> +
> + if (!strcmp(path, "/")) {
> + st->st_mode = S_IFDIR | 0755;
> + st->st_nlink = 2;
> + return 0;
> + }
> +
> + if (!strcmp(path, test_path)) {
> + st->st_mode = S_IFREG | 0664;
> + st->st_nlink = 1;
> + st->st_size = content_size;
> + return 0;
> + }
> +
> + return -ENOENT;
> +}
> +
> +static int test_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
> + off_t offset, struct fuse_file_info *fi)
> +{
> + if (strcmp(path, "/"))
> + return -ENOENT;
> +
> + filler(buf, ".", NULL, 0);
> + filler(buf, "..", NULL, 0);
> + filler(buf, test_path + 1, NULL, 0);
> +
> + return 0;
> +}
> +
> +static int test_open(const char *path, struct fuse_file_info *fi)
> +{
> + if (strcmp(path, test_path))
> + return -ENOENT;
> +
> + return 0;
> +}
> +
> +static int test_read(const char *path, char *buf, size_t size, off_t offset,
> + struct fuse_file_info *fi)
> +{
> + if (strcmp(path, test_path) != 0)
> + return -ENOENT;
> +
> + if (!content || content_size == 0)
> + return 0;
> +
> + if (offset >= content_size)
> + return 0;
> +
> + if (offset + size > content_size)
> + size = content_size - offset;
> +
> + memcpy(buf, content + offset, size);
> +
> + return size;
> +}
> +
> +static int test_write(const char *path, const char *buf, size_t size,
> + off_t offset, struct fuse_file_info *fi)
> +{
> + size_t new_size;
> +
> + if (strcmp(path, test_path) != 0)
> + return -ENOENT;
> +
> + if(offset > content_size)
> + return -EINVAL;
> +
> + new_size = MAX(offset + size, content_size);
> +
> + if (new_size > content_size)
> + content = realloc(content, new_size);
> +
> + content_size = new_size;
> +
> + if (!content)
> + return -ENOMEM;
> +
> + memcpy(content + offset, buf, size);
> +
> + return size;
> +}
> +
> +static int test_truncate(const char *path, off_t size)
> +{
> + if (strcmp(path, test_path) != 0)
> + return -ENOENT;
> +
> + if (size == 0) {
> + free(content);
> + content = NULL;
> + content_size = 0;
> + return 0;
> + }
> +
> + content = realloc(content, size);
> +
> + if (!content)
> + return -ENOMEM;
> +
> + if (size > content_size)
> + memset(content + content_size, 0, size - content_size);
> +
> + content_size = size;
> + return 0;
> +}
> +
> +static struct fuse_operations memfd_ops = {
> + .getattr = test_getattr,
> + .readdir = test_readdir,
> + .open = test_open,
> + .read = test_read,
> + .write = test_write,
> + .truncate = test_truncate,
> +};
> +
> +int main(int argc, char *argv[])
> +{
> + return fuse_main(argc, argv, &memfd_ops, NULL);
> +}
> diff --git a/tools/testing/selftests/filesystems/fusectl/fusectl_test.c b/tools/testing/selftests/filesystems/fusectl/fusectl_test.c
> new file mode 100644
> index 0000000000000..8ff130ae43122
> --- /dev/null
> +++ b/tools/testing/selftests/filesystems/fusectl/fusectl_test.c
> @@ -0,0 +1,115 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// Copyright (c) 2025 Chen Linxuan <chenlinxuan@uniontech.com>
> +
> +#define _GNU_SOURCE
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/mount.h>
> +#include <sys/stat.h>
> +#include <sys/types.h>
> +#include <sys/wait.h>
> +#include <unistd.h>
> +#include <dirent.h>
> +#include <linux/limits.h>
> +
> +#include "../../kselftest_harness.h"
> +
> +#define FUSECTL_MOUNTPOINT "/sys/fs/fuse/connections"
> +#define FUSE_MOUNTPOINT "/tmp/fuse_mnt_XXXXXX"
> +#define FUSE_DEVICE "/dev/fuse"
> +#define FUSECTL_TEST_VALUE "1"
> +
> +FIXTURE(fusectl){
> + char fuse_mountpoint[sizeof(FUSE_MOUNTPOINT)];
> + int connection;
> +};
> +
> +FIXTURE_SETUP(fusectl)
> +{
> + const char *fuse_mnt_prog = "./fuse_mnt";
> + int status, pid;
> + struct stat statbuf;
> +
> + strcpy(self->fuse_mountpoint, FUSE_MOUNTPOINT);
> +
> + if (!mkdtemp(self->fuse_mountpoint))
> + SKIP(return,
> + "Failed to create FUSE mountpoint %s",
> + strerror(errno));
> +
> + if (access(FUSECTL_MOUNTPOINT, F_OK))
> + SKIP(return,
> + "FUSE control filesystem not mounted");
> +
> + pid = fork();
> + if (pid < 0)
> + SKIP(return,
> + "Failed to fork FUSE daemon process: %s",
> + strerror(errno));
> +
> + if (pid == 0) {
> + execlp(fuse_mnt_prog, fuse_mnt_prog, self->fuse_mountpoint, NULL);
> + exit(errno);
> + }
> +
> + waitpid(pid, &status, 0);
> + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
> + SKIP(return,
> + "Failed to start FUSE daemon %s",
> + strerror(WEXITSTATUS(status)));
> + }
> +
> + if (stat(self->fuse_mountpoint, &statbuf))
> + SKIP(return,
> + "Failed to stat FUSE mountpoint %s",
> + strerror(errno));
> +
> + self->connection = statbuf.st_dev;
> +}
> +
> +FIXTURE_TEARDOWN(fusectl)
> +{
> + umount(self->fuse_mountpoint);
> + rmdir(self->fuse_mountpoint);
> +}
> +
> +TEST_F(fusectl, abort)
> +{
> + char path_buf[PATH_MAX];
> + int abort_fd, test_fd, ret;
> +
> + sprintf(path_buf, "/sys/fs/fuse/connections/%d/abort", self->connection);
> +
> + ASSERT_EQ(0, access(path_buf, F_OK));
> +
> + abort_fd = open(path_buf, O_WRONLY);
> + ASSERT_GE(abort_fd, 0);
> +
> + sprintf(path_buf, "%s/test", self->fuse_mountpoint);
> +
> + test_fd = open(path_buf, O_RDWR);
> + ASSERT_GE(test_fd, 0);
> +
> + ret = read(test_fd, path_buf, sizeof(path_buf));
> + ASSERT_EQ(ret, 0);
> +
> + ret = write(test_fd, "test", sizeof("test"));
> + ASSERT_EQ(ret, sizeof("test"));
> +
> + ret = lseek(test_fd, 0, SEEK_SET);
> + ASSERT_GE(ret, 0);
> +
> + ret = write(abort_fd, FUSECTL_TEST_VALUE, sizeof(FUSECTL_TEST_VALUE));
> + ASSERT_GT(ret, 0);
> +
> + close(abort_fd);
> +
> + ret = read(test_fd, path_buf, sizeof(path_buf));
> + ASSERT_LT(ret, 0);
Nice!
I guess you could also verify errno == ENOTCONN or whatever it is
in this case.
Thanks,
Amir.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] selftests: Add functional test for the abort file in fusectl
2025-05-15 10:26 ` Amir Goldstein
@ 2025-05-19 5:57 ` Chen Linxuan
2025-05-19 6:27 ` Amir Goldstein
0 siblings, 1 reply; 5+ messages in thread
From: Chen Linxuan @ 2025-05-19 5:57 UTC (permalink / raw)
To: Amir Goldstein
Cc: Chen Linxuan, Shuah Khan, Miklos Szeredi, zhanjun, niecheng1,
wentao, linux-kernel, linux-kselftest, linux-fsdevel
On Thu, May 15, 2025 at 6:27 PM Amir Goldstein <amir73il@gmail.com> wrote:
>
> On Thu, May 15, 2025 at 9:35 AM Chen Linxuan <chenlinxuan@uniontech.com> wrote:
> >
> > + ret = read(test_fd, path_buf, sizeof(path_buf));
> > + ASSERT_LT(ret, 0);
>
> Nice!
> I guess you could also verify errno == ENOTCONN or whatever it is
> in this case.
I am currently facing two issues:
1. I am not sure about the exact functions of max_background and
congestion_threshold. I have prepared a patch that adds documentation
for these two fields, which can be found here:
https://lore.kernel.org/all/20250514061703.483505-2-chenlinxuan@uniontech.com/
2. How should I test the "waiting" file? My current idea is to have my
FUSE daemon stay in a state where it does not respond to requests, and
then use some form of inter-process communication (maybe a Unix
socket?) to make it resume working. I am not sure if there is a better
approach.
Thanks,
Chen Linxuan.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] selftests: Add functional test for the abort file in fusectl
2025-05-19 5:57 ` Chen Linxuan
@ 2025-05-19 6:27 ` Amir Goldstein
0 siblings, 0 replies; 5+ messages in thread
From: Amir Goldstein @ 2025-05-19 6:27 UTC (permalink / raw)
To: Chen Linxuan
Cc: Shuah Khan, Miklos Szeredi, zhanjun, niecheng1, wentao,
linux-kernel, linux-kselftest, linux-fsdevel
On Mon, May 19, 2025 at 7:58 AM Chen Linxuan <chenlinxuan@uniontech.com> wrote:
>
> On Thu, May 15, 2025 at 6:27 PM Amir Goldstein <amir73il@gmail.com> wrote:
> >
> > On Thu, May 15, 2025 at 9:35 AM Chen Linxuan <chenlinxuan@uniontech.com> wrote:
> > >
> > > + ret = read(test_fd, path_buf, sizeof(path_buf));
> > > + ASSERT_LT(ret, 0);
> >
> > Nice!
> > I guess you could also verify errno == ENOTCONN or whatever it is
> > in this case.
>
> I am currently facing two issues:
>
> 1. I am not sure about the exact functions of max_background and
> congestion_threshold. I have prepared a patch that adds documentation
> for these two fields, which can be found here:
> https://lore.kernel.org/all/20250514061703.483505-2-chenlinxuan@uniontech.com/
It may be a bit challenging to design a test that does deterministic
readahead, because there is usually no contract for readahead,
so not sure.
>
> 2. How should I test the "waiting" file? My current idea is to have my
> FUSE daemon stay in a state where it does not respond to requests, and
> then use some form of inter-process communication (maybe a Unix
> socket?) to make it resume working. I am not sure if there is a better
> approach.
This is a good approach that several selftests use.
Looking at the bigger picture, your work to improve documentation and
selftest coverage for fuse is very welcome! so I will add some wider
context comments.
One small nit: please rename the test subdir to filesystems/fuse rather
than filesystems/fusectl, so that more fuse selftests could be added later.
For the long run, I would consider a very minimal single threaded
fuse server implementation that does not rely on libfuse for fuse selftests,
because the selftest should not rely on the libfuse version installed on
the development system and also testing low level protocol issues
would require this anyway.
But this is not a requirement for this first test.
Thanks,
Amir.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2025-05-19 6:27 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-15 7:34 [PATCH] selftests: Add functional test for the abort file in fusectl Chen Linxuan
2025-05-15 7:44 ` Chen Linxuan
2025-05-15 10:26 ` Amir Goldstein
2025-05-19 5:57 ` Chen Linxuan
2025-05-19 6:27 ` Amir Goldstein
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).