* [PATCH BlueZ 0/2] test-runner: use virtio-fs by default, functional test speedup @ 2026-09-10 16:48 Pauli Virtanen 2026-09-10 16:48 ` [PATCH BlueZ 1/2] doc: enable virtio-fs in tester kernel configs Pauli Virtanen 2026-09-10 16:48 ` [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough Pauli Virtanen 0 siblings, 2 replies; 6+ messages in thread From: Pauli Virtanen @ 2026-09-10 16:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Pauli Virtanen Use virtio-fs instead of 9p, which gives 3x reduction in CPU time for functional tests: Before: $ time make check-functional real 2m9,736s user 1m29,570s sys 0m32,715s After: $ time make check-functional real 1m35,703s user 0m28,938s sys 0m7,453s Wall clock improvement becomes more significant under CPU load. Requires /usr/libexec/virtiofsd installed, and CONFIG_VIRTIO_FS=y in kernel. Enable that option in tester configs. If virtiofsd is not available, fall back to 9p as before. Pauli Virtanen (2): doc: enable virtio-fs in tester kernel configs tools: test-runner: use virtiofsd for filesystem passthrough doc/ci.config | 2 + doc/test-runner.rst | 3 + doc/tester.config | 2 + tools/test-runner.c | 210 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 203 insertions(+), 14 deletions(-) -- 2.55.0 ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH BlueZ 1/2] doc: enable virtio-fs in tester kernel configs 2026-09-10 16:48 [PATCH BlueZ 0/2] test-runner: use virtio-fs by default, functional test speedup Pauli Virtanen @ 2026-09-10 16:48 ` Pauli Virtanen 2026-09-10 19:30 ` test-runner: use virtio-fs by default, functional test speedup bluez.test.bot 2026-09-10 16:48 ` [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough Pauli Virtanen 1 sibling, 1 reply; 6+ messages in thread From: Pauli Virtanen @ 2026-09-10 16:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Pauli Virtanen Add support for virtio-fs in tester configs. --- doc/ci.config | 2 ++ doc/tester.config | 2 ++ 2 files changed, 4 insertions(+) diff --git a/doc/ci.config b/doc/ci.config index 2da3e14c4..99d59c5d3 100644 --- a/doc/ci.config +++ b/doc/ci.config @@ -7,6 +7,8 @@ CONFIG_VIRTIO=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_FS=y +CONFIG_FUSE_FS=y CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y diff --git a/doc/tester.config b/doc/tester.config index b9c5f34bc..e68740dc0 100644 --- a/doc/tester.config +++ b/doc/tester.config @@ -2,6 +2,8 @@ CONFIG_PCI=y CONFIG_VIRTIO=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_FS=y +CONFIG_FUSE_FS=y CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: test-runner: use virtio-fs by default, functional test speedup 2026-09-10 16:48 ` [PATCH BlueZ 1/2] doc: enable virtio-fs in tester kernel configs Pauli Virtanen @ 2026-09-10 19:30 ` bluez.test.bot 0 siblings, 0 replies; 6+ messages in thread From: bluez.test.bot @ 2026-09-10 19:30 UTC (permalink / raw) To: linux-bluetooth, pav [-- Attachment #1: Type: text/plain, Size: 2434 bytes --] This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/series/1162236/ ---Test result--- Test Summary: CheckPatch FAIL 1.09 seconds GitLint FAIL 0.64 seconds BuildEll PASS 19.55 seconds BluezMake PASS 378.20 seconds MakeCheck PASS 14.21 seconds MakeDistcheck PASS 139.98 seconds CheckValgrind PASS 231.49 seconds CheckSmatch PASS 291.19 seconds bluezmakeextell PASS 93.97 seconds IncrementalBuild PASS 375.56 seconds ScanBuild PASS 1118.25 seconds Details ############################## Test: CheckPatch - FAIL Desc: Run checkpatch.pl script Output: [BlueZ,2/2] tools: test-runner: use virtiofsd for filesystem passthrough WARNING:STATIC_CONST_CHAR_ARRAY: char * array declaration might be better as static const #188: FILE: tools/test-runner.c:525: + const char *cmd[] = { /github/workspace/src/patch/14805955.patch total: 0 errors, 1 warnings, 334 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/patch/14805955.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. ############################## Test: GitLint - FAIL Desc: Run gitlint Output: [BlueZ,2/2] tools: test-runner: use virtiofsd for filesystem passthrough 14: B3 Line contains hard tab characters (\t): "real 2m9,736s" 15: B3 Line contains hard tab characters (\t): "user 1m29,570s" 16: B3 Line contains hard tab characters (\t): "sys 0m32,715s" 20: B3 Line contains hard tab characters (\t): "real 1m35,703s" 21: B3 Line contains hard tab characters (\t): "user 0m28,938s" 22: B3 Line contains hard tab characters (\t): "sys 0m7,453s" https://github.com/bluez/bluez/pull/2517 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough 2026-09-10 16:48 [PATCH BlueZ 0/2] test-runner: use virtio-fs by default, functional test speedup Pauli Virtanen 2026-09-10 16:48 ` [PATCH BlueZ 1/2] doc: enable virtio-fs in tester kernel configs Pauli Virtanen @ 2026-09-10 16:48 ` Pauli Virtanen 2026-09-10 17:16 ` Luiz Augusto von Dentz 1 sibling, 1 reply; 6+ messages in thread From: Pauli Virtanen @ 2026-09-10 16:48 UTC (permalink / raw) To: linux-bluetooth; +Cc: Pauli Virtanen The 9p mount passthrough I/O is fairly CPU hungry and slow. This matters for e.g. running Python in test-runner, since it has to read some amount of files for startup. Add support for virtio-fs, which is significantly less CPU intensive. Enable it by default if /usr/libexec/virtiofsd is available, fall back to 9p if virtiofsd not usable. Before: $ time make check-functional real 2m9,736s user 1m29,570s sys 0m32,715s After: $ time make check-functional real 1m35,703s user 0m28,938s sys 0m7,453s --- doc/test-runner.rst | 3 + tools/test-runner.c | 210 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 199 insertions(+), 14 deletions(-) diff --git a/doc/test-runner.rst b/doc/test-runner.rst index 6787507c3..ac8f22c19 100644 --- a/doc/test-runner.rst +++ b/doc/test-runner.rst @@ -26,6 +26,7 @@ OPTIONS :-P/--pcie=<qemu_args>: Provide PCIe device :-q/--qemu=<path>: QEMU binary :-k/--kernel=<image>: Kernel image (bzImage) +:-F/--virtiofs=<virtiofsd / no>: Enable/disable use of virtio-fs. :-h/--help: Show help options Kernel @@ -47,6 +48,8 @@ option (like the Bluetooth subsystem) can be enabled on top of this. CONFIG_VIRTIO=y CONFIG_VIRTIO_PCI=y CONFIG_VIRTIO_CONSOLE=y + CONFIG_VIRTIO_FS=y + CONFIG_FUSE_FS=y CONFIG_NET=y CONFIG_INET=y diff --git a/tools/test-runner.c b/tools/test-runner.c index 63fedece0..d6589f7a9 100644 --- a/tools/test-runner.c +++ b/tools/test-runner.c @@ -64,6 +64,7 @@ static char *usb_dev; static char *pcie_dev; static char *extra_opts[EXTRA_OPT_MAX]; static int num_extra_opts; +static const char *virtiofsd = "/usr/libexec/virtiofsd"; static const char *qemu_table[] = { "qemu-system-x86_64", @@ -235,9 +236,6 @@ static char *const qemu_argv[] = { "-m", "256M", "-net", "none", "-no-reboot", - "-fsdev", "local,id=fsdev-root,path=/,readonly=on,security_model=none," - "multidevs=remap", - "-device", "virtio-9p-pci,fsdev=fsdev-root,mount_tag=/dev/root", "-chardev", "stdio,id=con,mux=on", "-serial", "chardev:con", "-device", "virtio-serial", @@ -495,6 +493,98 @@ static void pcie_unbind_vfio(void) pcie_probe(pcie_bdf); } +static bool check_virtiofsd(void) +{ + if (!virtiofsd) + return false; + + if (access(virtiofsd, X_OK)) { + fprintf(stderr, "%s not available", virtiofsd); + return false; + } + + return true; +} + +static pid_t start_virtiofsd(const char *tmpdir) +{ + pid_t pid; + char path[PATH_MAX]; + struct stat st; + + printf("Using virtiofsd %s\n", virtiofsd); + + snprintf(path, sizeof(path), "%s/virtiofs", tmpdir); + + pid = fork(); + if (pid < 0) + return pid; + + if (pid == 0) { + char *envp[1]; + const char *cmd[] = { + virtiofsd, + "--socket-path", path, + "--shared-dir", "/", + "--readonly", + "--tag", "/dev/root", + /* Drop unnecessary capabilities, if run as root */ + "--modcaps=-chown:-dac_override:-fowner:-fsetid:" + "-setgid:-setuid:-mknod:-setfcap", + /* + * Disabling namespace sandbox is needed to allow the + * guest to mount other virtio/9p filesystems. + */ + "--sandbox", "none", + NULL + }; + + envp[0] = NULL; + execve(cmd[0], (char **)cmd, envp); + exit(EXIT_SUCCESS); + } + + while (1) { + int status; + pid_t ret; + + if (!stat(path, &st)) + break; + + ret = waitpid(pid, &status, WNOHANG); + if (ret < 0 && errno == -EINTR) + continue; + else if (ret) + return -EIO; + + sleep(1); + } + + return pid; +} + +static void cleanup_virtiofsd(pid_t pid, const char *tmpdir) +{ + char path[PATH_MAX]; + int status; + + if (pid > 0) { + kill(pid, SIGTERM); + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) + break; + } + } + + if (tmpdir[0]) { + snprintf(path, sizeof(path), "%s/virtiofs", tmpdir); + unlink(path); + snprintf(path, sizeof(path), "%s/virtiofs.pid", tmpdir); + unlink(path); + rmdir(tmpdir); + } +} + static pid_t qemu_pid; /* Forwards the signal to QEMU so it can shutdown, the host driver is then @@ -509,10 +599,13 @@ static void qemu_signal(int sig) static int start_qemu(void) { char cwd[PATH_MAX/2], initcmd[PATH_MAX], testargs[PATH_MAX]; + const char *fscmdline; char cmdline[CMDLINE_MAX]; + char tmpdir[PATH_MAX] = {0}; char **argv; int i, pos, status = 0; pid_t pid; + pid_t virtiofsd_pid = -1; check_virtualization(); @@ -539,15 +632,20 @@ static int start_qemu(void) pos += n; } + if (!virtiofsd) + fscmdline = "rootfstype=9p " + "rootflags=trans=virtio,version=9p2000.u"; + else + fscmdline = "rootfstype=virtiofs root=/dev/root"; + snprintf(cmdline, sizeof(cmdline), "console=hvc0 earlyprintk=serial " - "no_hash_pointers=1 rootfstype=9p " - "rootflags=trans=virtio,version=9p2000.u " - "%s quiet ro init=%s " + "no_hash_pointers=1 %s %s quiet ro init=%s " "TESTHOME=%s TESTDBUS=%u TESTDAEMON=%u " "TESTDBUSSESSION=%u XDG_RUNTIME_DIR=/run/user/0 " "TESTMONITOR=%u TESTEMULATOR=%u TESTDEVS=%d " "TESTAUTO=%u TESTAUDIO='%s' TESTARGS=\'%s\'", + fscmdline, /* PCIe passthrough requires ACPI and APIC for * device enumeration and MSI interrupts. */ @@ -559,6 +657,7 @@ static int start_qemu(void) testargs); argv = alloca(sizeof(qemu_argv) + + sizeof(char *) * 8 + (sizeof(char *) * (8 + (num_devs * 4))) + (sizeof(char *) * (usb_dev ? 4 : 0)) + (sizeof(char *) * (pcie_dev ? 2 : 0)) + @@ -567,6 +666,60 @@ static int start_qemu(void) pos = (sizeof(qemu_argv) / sizeof(char *)) - 1; + if (!virtiofsd) { + argv[pos++] = "-fsdev"; + argv[pos++] = "local,id=fsdev-root,path=/,readonly=on," + "security_model=none,multidevs=remap"; + argv[pos++] = "-device"; + argv[pos++] = "virtio-9p-pci,fsdev=fsdev-root," + "mount_tag=/dev/root"; + } else { + char *chrdev; + const char *tmp_base; + const char *mem = "256M"; + char *memdev; + + tmp_base = getenv("TMPDIR"); + if (!tmp_base) + tmp_base = "/tmp"; + + snprintf(tmpdir, sizeof(tmpdir), "%s/bluez-test-runner.XXXXXX", + tmp_base); + if (!mkdtemp(tmpdir)) { + perror("mkdtemp failed"); + return EXIT_FAILURE; + } + + chrdev = alloca(48 + strlen(tmpdir)); + sprintf(chrdev, "socket,id=virtiofs0,path=%s/virtiofs", tmpdir); + + argv[pos++] = "-chardev"; + argv[pos++] = chrdev; + argv[pos++] = "-device"; + argv[pos++] = "vhost-user-fs-pci,queue-size=1024," + "chardev=virtiofs0,tag=/dev/root"; + + /* Find out memory size */ + for (i = 0; i < pos; ++i) { + if (strcmp(argv[i], "-m") == 0 && i + 1 < pos) + mem = argv[i+1]; + } + for (i = 0; i < num_extra_opts; ++i) { + if (strcmp(extra_opts[i], "-m") == 0 && + i + 1 < num_extra_opts) + mem = extra_opts[i+1]; + } + + memdev = alloca(48 + strlen(mem)); + sprintf(memdev, "memory-backend-memfd,id=mem0,size=%s,share=on", + mem); + + argv[pos++] = "-object"; + argv[pos++] = memdev; + argv[pos++] = "-numa"; + argv[pos++] = "node,memdev=mem0"; + } + /* Make sure qemu_binary is not null */ if (!qemu_binary) { fprintf(stderr, "No QEMU binary is set\n"); @@ -616,21 +769,29 @@ static int start_qemu(void) argv[pos] = NULL; - if (!pcie_dev) { + /* Exec directly if no setup/cleanup needed */ + if (!pcie_dev && !virtiofsd) { execve(argv[0], argv, qemu_envp); return EXIT_FAILURE; } - /* With a device passed through the host driver has to be restored - * once the guest is done with it, so QEMU cannot simply replace this - * process here. - */ - pcie_bind_vfio(); + if (virtiofsd) { + virtiofsd_pid = start_virtiofsd(tmpdir); + if (virtiofsd_pid < 0) { + perror("Failed to start virtiofsd"); + cleanup_virtiofsd(virtiofsd_pid, tmpdir); + return EXIT_FAILURE; + } + } + + if (pcie_dev) + pcie_bind_vfio(); pid = fork(); if (pid < 0) { perror("Failed to fork new process"); pcie_unbind_vfio(); + cleanup_virtiofsd(virtiofsd_pid, tmpdir); return EXIT_FAILURE; } @@ -655,7 +816,11 @@ static int start_qemu(void) qemu_pid = -1; - pcie_unbind_vfio(); + if (pcie_dev) + pcie_unbind_vfio(); + + if (virtiofsd) + cleanup_virtiofsd(virtiofsd_pid, tmpdir); return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; } @@ -1524,6 +1689,7 @@ static void usage(void) "\t-q, --qemu <path> QEMU binary\n" "\t-H, --qemu-host-cpu Use host CPU (requires KVM support)\n" "\t-k, --kernel <image> Kernel bzImage or source tree path\n" + "\t-F, --virtiofs[=no / virtiofsd] Virtiofsd disable / path\n" "\t-o, --option <opt> Additional argument passed to QEMU\n" "\t-h, --help Show help options\n"); } @@ -1544,6 +1710,7 @@ static const struct option main_options[] = { { "usb", required_argument, NULL, 'U' }, { "pcie", required_argument, NULL, 'P' }, { "option", required_argument, NULL, 'o' }, + { "virtiofs", optional_argument, NULL, 'F' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { } @@ -1552,6 +1719,7 @@ static const struct option main_options[] = { int main(int argc, char *argv[]) { char kernel_path[PATH_MAX]; + bool virtiofs_auto = true; if (getpid() == 1 && getppid() == 0) { prepare_sandbox(); @@ -1565,7 +1733,7 @@ int main(int argc, char *argv[]) for (;;) { int opt; - opt = getopt_long(argc, argv, "au::bdsl::mq:Hk:A::U:P:o:vh", + opt = getopt_long(argc, argv, "au::bdsl::mq:Hk:A::U:P:o:F::vh", main_options, NULL); if (opt < 0) break; @@ -1620,6 +1788,15 @@ int main(int argc, char *argv[]) } extra_opts[num_extra_opts++] = optarg; break; + case 'F': + virtiofs_auto = false; + if (optarg) { + if (strcmp(optarg, "no") == 0) + virtiofsd = NULL; + else + virtiofsd = optarg; + } + break; case 'v': printf("%s\n", VERSION); return EXIT_SUCCESS; @@ -1631,6 +1808,11 @@ int main(int argc, char *argv[]) } } + if (virtiofs_auto && !check_virtiofsd()) { + fprintf(stderr, ": virtiofs disabled\n"); + virtiofsd = NULL; + } + if (run_auto) { if (argc - optind > 0) { fprintf(stderr, "Invalid command line parameters\n"); -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough 2026-09-10 16:48 ` [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough Pauli Virtanen @ 2026-09-10 17:16 ` Luiz Augusto von Dentz 0 siblings, 0 replies; 6+ messages in thread From: Luiz Augusto von Dentz @ 2026-09-10 17:16 UTC (permalink / raw) To: Pauli Virtanen; +Cc: linux-bluetooth Hi Pauli, On Thu, Sep 10, 2026 at 1:10 PM Pauli Virtanen <pav@iki.fi> wrote: > > The 9p mount passthrough I/O is fairly CPU hungry and slow. This matters > for e.g. running Python in test-runner, since it has to read some amount > of files for startup. > > Add support for virtio-fs, which is significantly less CPU intensive. > > Enable it by default if /usr/libexec/virtiofsd is available, fall back > to 9p if virtiofsd not usable. > > Before: > $ time make check-functional > real 2m9,736s > user 1m29,570s > sys 0m32,715s > > After: > $ time make check-functional > real 1m35,703s > user 0m28,938s > sys 0m7,453s > --- > doc/test-runner.rst | 3 + > tools/test-runner.c | 210 +++++++++++++++++++++++++++++++++++++++++--- > 2 files changed, 199 insertions(+), 14 deletions(-) > > diff --git a/doc/test-runner.rst b/doc/test-runner.rst > index 6787507c3..ac8f22c19 100644 > --- a/doc/test-runner.rst > +++ b/doc/test-runner.rst > @@ -26,6 +26,7 @@ OPTIONS > :-P/--pcie=<qemu_args>: Provide PCIe device > :-q/--qemu=<path>: QEMU binary > :-k/--kernel=<image>: Kernel image (bzImage) > +:-F/--virtiofs=<virtiofsd / no>: Enable/disable use of virtio-fs. > :-h/--help: Show help options > > Kernel > @@ -47,6 +48,8 @@ option (like the Bluetooth subsystem) can be enabled on top of this. > CONFIG_VIRTIO=y > CONFIG_VIRTIO_PCI=y > CONFIG_VIRTIO_CONSOLE=y > + CONFIG_VIRTIO_FS=y > + CONFIG_FUSE_FS=y > > CONFIG_NET=y > CONFIG_INET=y > diff --git a/tools/test-runner.c b/tools/test-runner.c > index 63fedece0..d6589f7a9 100644 > --- a/tools/test-runner.c > +++ b/tools/test-runner.c > @@ -64,6 +64,7 @@ static char *usb_dev; > static char *pcie_dev; > static char *extra_opts[EXTRA_OPT_MAX]; > static int num_extra_opts; > +static const char *virtiofsd = "/usr/libexec/virtiofsd"; > > static const char *qemu_table[] = { > "qemu-system-x86_64", > @@ -235,9 +236,6 @@ static char *const qemu_argv[] = { > "-m", "256M", > "-net", "none", > "-no-reboot", > - "-fsdev", "local,id=fsdev-root,path=/,readonly=on,security_model=none," > - "multidevs=remap", > - "-device", "virtio-9p-pci,fsdev=fsdev-root,mount_tag=/dev/root", > "-chardev", "stdio,id=con,mux=on", > "-serial", "chardev:con", > "-device", "virtio-serial", > @@ -495,6 +493,98 @@ static void pcie_unbind_vfio(void) > pcie_probe(pcie_bdf); > } > > +static bool check_virtiofsd(void) > +{ > + if (!virtiofsd) > + return false; > + > + if (access(virtiofsd, X_OK)) { > + fprintf(stderr, "%s not available", virtiofsd); > + return false; > + } > + > + return true; > +} > + > +static pid_t start_virtiofsd(const char *tmpdir) > +{ > + pid_t pid; > + char path[PATH_MAX]; > + struct stat st; > + > + printf("Using virtiofsd %s\n", virtiofsd); > + > + snprintf(path, sizeof(path), "%s/virtiofs", tmpdir); > + > + pid = fork(); > + if (pid < 0) > + return pid; > + > + if (pid == 0) { > + char *envp[1]; > + const char *cmd[] = { > + virtiofsd, > + "--socket-path", path, > + "--shared-dir", "/", > + "--readonly", > + "--tag", "/dev/root", > + /* Drop unnecessary capabilities, if run as root */ > + "--modcaps=-chown:-dac_override:-fowner:-fsetid:" > + "-setgid:-setuid:-mknod:-setfcap", > + /* > + * Disabling namespace sandbox is needed to allow the > + * guest to mount other virtio/9p filesystems. > + */ > + "--sandbox", "none", > + NULL > + }; > + > + envp[0] = NULL; > + execve(cmd[0], (char **)cmd, envp); > + exit(EXIT_SUCCESS); > + } > + > + while (1) { > + int status; > + pid_t ret; > + > + if (!stat(path, &st)) > + break; > + > + ret = waitpid(pid, &status, WNOHANG); > + if (ret < 0 && errno == -EINTR) > + continue; > + else if (ret) > + return -EIO; > + > + sleep(1); > + } > + > + return pid; > +} > + > +static void cleanup_virtiofsd(pid_t pid, const char *tmpdir) > +{ > + char path[PATH_MAX]; > + int status; > + > + if (pid > 0) { > + kill(pid, SIGTERM); > + while (waitpid(pid, &status, 0) < 0) { > + if (errno != EINTR) > + break; > + } > + } > + > + if (tmpdir[0]) { > + snprintf(path, sizeof(path), "%s/virtiofs", tmpdir); > + unlink(path); > + snprintf(path, sizeof(path), "%s/virtiofs.pid", tmpdir); > + unlink(path); > + rmdir(tmpdir); > + } > +} > + > static pid_t qemu_pid; > > /* Forwards the signal to QEMU so it can shutdown, the host driver is then > @@ -509,10 +599,13 @@ static void qemu_signal(int sig) > static int start_qemu(void) > { > char cwd[PATH_MAX/2], initcmd[PATH_MAX], testargs[PATH_MAX]; > + const char *fscmdline; > char cmdline[CMDLINE_MAX]; > + char tmpdir[PATH_MAX] = {0}; > char **argv; > int i, pos, status = 0; > pid_t pid; > + pid_t virtiofsd_pid = -1; > > check_virtualization(); > > @@ -539,15 +632,20 @@ static int start_qemu(void) > pos += n; > } > > + if (!virtiofsd) > + fscmdline = "rootfstype=9p " > + "rootflags=trans=virtio,version=9p2000.u"; > + else > + fscmdline = "rootfstype=virtiofs root=/dev/root"; > + > snprintf(cmdline, sizeof(cmdline), > "console=hvc0 earlyprintk=serial " > - "no_hash_pointers=1 rootfstype=9p " > - "rootflags=trans=virtio,version=9p2000.u " > - "%s quiet ro init=%s " > + "no_hash_pointers=1 %s %s quiet ro init=%s " > "TESTHOME=%s TESTDBUS=%u TESTDAEMON=%u " > "TESTDBUSSESSION=%u XDG_RUNTIME_DIR=/run/user/0 " > "TESTMONITOR=%u TESTEMULATOR=%u TESTDEVS=%d " > "TESTAUTO=%u TESTAUDIO='%s' TESTARGS=\'%s\'", > + fscmdline, > /* PCIe passthrough requires ACPI and APIC for > * device enumeration and MSI interrupts. > */ > @@ -559,6 +657,7 @@ static int start_qemu(void) > testargs); > > argv = alloca(sizeof(qemu_argv) + > + sizeof(char *) * 8 + > (sizeof(char *) * (8 + (num_devs * 4))) + > (sizeof(char *) * (usb_dev ? 4 : 0)) + > (sizeof(char *) * (pcie_dev ? 2 : 0)) + > @@ -567,6 +666,60 @@ static int start_qemu(void) > > pos = (sizeof(qemu_argv) / sizeof(char *)) - 1; > > + if (!virtiofsd) { > + argv[pos++] = "-fsdev"; > + argv[pos++] = "local,id=fsdev-root,path=/,readonly=on," > + "security_model=none,multidevs=remap"; > + argv[pos++] = "-device"; > + argv[pos++] = "virtio-9p-pci,fsdev=fsdev-root," > + "mount_tag=/dev/root"; > + } else { > + char *chrdev; > + const char *tmp_base; > + const char *mem = "256M"; > + char *memdev; > + > + tmp_base = getenv("TMPDIR"); > + if (!tmp_base) > + tmp_base = "/tmp"; > + > + snprintf(tmpdir, sizeof(tmpdir), "%s/bluez-test-runner.XXXXXX", > + tmp_base); > + if (!mkdtemp(tmpdir)) { > + perror("mkdtemp failed"); > + return EXIT_FAILURE; > + } > + > + chrdev = alloca(48 + strlen(tmpdir)); > + sprintf(chrdev, "socket,id=virtiofs0,path=%s/virtiofs", tmpdir); > + > + argv[pos++] = "-chardev"; > + argv[pos++] = chrdev; > + argv[pos++] = "-device"; > + argv[pos++] = "vhost-user-fs-pci,queue-size=1024," > + "chardev=virtiofs0,tag=/dev/root"; > + > + /* Find out memory size */ > + for (i = 0; i < pos; ++i) { > + if (strcmp(argv[i], "-m") == 0 && i + 1 < pos) > + mem = argv[i+1]; > + } > + for (i = 0; i < num_extra_opts; ++i) { > + if (strcmp(extra_opts[i], "-m") == 0 && > + i + 1 < num_extra_opts) > + mem = extra_opts[i+1]; > + } > + > + memdev = alloca(48 + strlen(mem)); > + sprintf(memdev, "memory-backend-memfd,id=mem0,size=%s,share=on", > + mem); > + > + argv[pos++] = "-object"; > + argv[pos++] = memdev; > + argv[pos++] = "-numa"; > + argv[pos++] = "node,memdev=mem0"; > + } There quite a lot of code being added to this function, perhaps it should be placed into a helper function that init the args for the filesystem of choice. > /* Make sure qemu_binary is not null */ > if (!qemu_binary) { > fprintf(stderr, "No QEMU binary is set\n"); > @@ -616,21 +769,29 @@ static int start_qemu(void) > > argv[pos] = NULL; > > - if (!pcie_dev) { > + /* Exec directly if no setup/cleanup needed */ > + if (!pcie_dev && !virtiofsd) { > execve(argv[0], argv, qemu_envp); > return EXIT_FAILURE; > } > > - /* With a device passed through the host driver has to be restored > - * once the guest is done with it, so QEMU cannot simply replace this > - * process here. > - */ > - pcie_bind_vfio(); > + if (virtiofsd) { > + virtiofsd_pid = start_virtiofsd(tmpdir); > + if (virtiofsd_pid < 0) { > + perror("Failed to start virtiofsd"); > + cleanup_virtiofsd(virtiofsd_pid, tmpdir); > + return EXIT_FAILURE; > + } > + } > + > + if (pcie_dev) > + pcie_bind_vfio(); > > pid = fork(); > if (pid < 0) { > perror("Failed to fork new process"); > pcie_unbind_vfio(); > + cleanup_virtiofsd(virtiofsd_pid, tmpdir); > return EXIT_FAILURE; > } > > @@ -655,7 +816,11 @@ static int start_qemu(void) > > qemu_pid = -1; > > - pcie_unbind_vfio(); > + if (pcie_dev) > + pcie_unbind_vfio(); > + > + if (virtiofsd) > + cleanup_virtiofsd(virtiofsd_pid, tmpdir); > > return WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE; > } > @@ -1524,6 +1689,7 @@ static void usage(void) > "\t-q, --qemu <path> QEMU binary\n" > "\t-H, --qemu-host-cpu Use host CPU (requires KVM support)\n" > "\t-k, --kernel <image> Kernel bzImage or source tree path\n" > + "\t-F, --virtiofs[=no / virtiofsd] Virtiofsd disable / path\n" > "\t-o, --option <opt> Additional argument passed to QEMU\n" > "\t-h, --help Show help options\n"); > } > @@ -1544,6 +1710,7 @@ static const struct option main_options[] = { > { "usb", required_argument, NULL, 'U' }, > { "pcie", required_argument, NULL, 'P' }, > { "option", required_argument, NULL, 'o' }, > + { "virtiofs", optional_argument, NULL, 'F' }, > { "version", no_argument, NULL, 'v' }, > { "help", no_argument, NULL, 'h' }, > { } > @@ -1552,6 +1719,7 @@ static const struct option main_options[] = { > int main(int argc, char *argv[]) > { > char kernel_path[PATH_MAX]; > + bool virtiofs_auto = true; > > if (getpid() == 1 && getppid() == 0) { > prepare_sandbox(); > @@ -1565,7 +1733,7 @@ int main(int argc, char *argv[]) > for (;;) { > int opt; > > - opt = getopt_long(argc, argv, "au::bdsl::mq:Hk:A::U:P:o:vh", > + opt = getopt_long(argc, argv, "au::bdsl::mq:Hk:A::U:P:o:F::vh", > main_options, NULL); > if (opt < 0) > break; > @@ -1620,6 +1788,15 @@ int main(int argc, char *argv[]) > } > extra_opts[num_extra_opts++] = optarg; > break; > + case 'F': > + virtiofs_auto = false; > + if (optarg) { > + if (strcmp(optarg, "no") == 0) > + virtiofsd = NULL; > + else > + virtiofsd = optarg; > + } > + break; > case 'v': > printf("%s\n", VERSION); > return EXIT_SUCCESS; > @@ -1631,6 +1808,11 @@ int main(int argc, char *argv[]) > } > } > > + if (virtiofs_auto && !check_virtiofsd()) { > + fprintf(stderr, ": virtiofs disabled\n"); > + virtiofsd = NULL; > + } > + > if (run_auto) { > if (argc - optind > 0) { > fprintf(stderr, "Invalid command line parameters\n"); > -- > 2.55.0 > > -- Luiz Augusto von Dentz ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH BlueZ v2 1/4] tools/test-runner: replace alloca() based argv setup @ 2026-09-12 18:18 Pauli Virtanen 2026-09-12 19:17 ` test-runner: use virtio-fs by default, functional test speedup bluez.test.bot 0 siblings, 1 reply; 6+ messages in thread From: Pauli Virtanen @ 2026-09-12 18:18 UTC (permalink / raw) To: linux-bluetooth; +Cc: Pauli Virtanen Rewrite alloca() based argv array construction that required manual size counting with vasprintf string array. This allows splitting start_qemu() to multiple functions. --- tools/test-runner.c | 132 +++++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 43 deletions(-) diff --git a/tools/test-runner.c b/tools/test-runner.c index 63fedece0..a0ac321ca 100644 --- a/tools/test-runner.c +++ b/tools/test-runner.c @@ -21,6 +21,7 @@ #include <stdbool.h> #include <signal.h> #include <string.h> +#include <stdarg.h> #include <getopt.h> #include <poll.h> #include <dirent.h> @@ -41,6 +42,10 @@ #define WAIT_ANY (-1) #endif +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define _cleanup_(f) __attribute__((cleanup(f))) + #define CMDLINE_MAX (2048 * 10) #define EXTRA_OPT_MAX 64 @@ -65,6 +70,58 @@ static char *pcie_dev; static char *extra_opts[EXTRA_OPT_MAX]; static int num_extra_opts; +struct strv { + char **strv; + size_t size; + size_t i; +}; + +#define STRV_ERROR(s) ((s).size == 0) + +static void __attribute__((format(printf, 2, 3))) +strv_append(struct strv *s, const char *fmt, ...) +{ + va_list ap; + int ret; + + if (s->size == 0 || s->i >= s->size - 1) + goto fail; + + va_start(ap, fmt); + ret = vasprintf(&s->strv[s->i], fmt, ap); + va_end(ap); + + if (ret < 0) { + perror("vasprintf"); + s->strv[s->i] = NULL; + goto fail; + } + + s->strv[++s->i] = NULL; + return; + +fail: + s->size = 0; +} + +static void strv_concat(struct strv *s, const char *const *str) +{ + while (*str) { + strv_append(s, "%s", *str); + str++; + } +} + +static void strv_cleanup(struct strv *s) +{ + size_t i; + + for (i = 0; i < s->i; ++i) + free(s->strv[i]); + + memset(s, 0, sizeof(*s)); +} + static const char *qemu_table[] = { "qemu-system-x86_64", "qemu-system-i386", @@ -225,8 +282,7 @@ static void prepare_sandbox(void) enable_printk(); } -static char *const qemu_argv[] = { - "", +static const char *const qemu_argv[] = { "-nodefaults", "-no-user-config", "-monitor", "none", @@ -510,7 +566,9 @@ static int start_qemu(void) { char cwd[PATH_MAX/2], initcmd[PATH_MAX], testargs[PATH_MAX]; char cmdline[CMDLINE_MAX]; - char **argv; + char *argv_strv[EXTRA_OPT_MAX + 64]; + struct strv _cleanup_(strv_cleanup) argv = { argv_strv, + ARRAY_SIZE(argv_strv) }; int i, pos, status = 0; pid_t pid; @@ -533,7 +591,7 @@ static int start_qemu(void) if (n < 0 || n >= len) { fprintf(stderr, "Buffer overflow detected in " "testargs\n"); - exit(EXIT_FAILURE); + return EXIT_FAILURE; } pos += n; @@ -558,66 +616,54 @@ static int start_qemu(void) run_auto, audio_server ? audio_server : "", testargs); - argv = alloca(sizeof(qemu_argv) + - (sizeof(char *) * (8 + (num_devs * 4))) + - (sizeof(char *) * (usb_dev ? 4 : 0)) + - (sizeof(char *) * (pcie_dev ? 2 : 0)) + - (sizeof(char *) * num_extra_opts)); - memcpy(argv, qemu_argv, sizeof(qemu_argv)); - - pos = (sizeof(qemu_argv) / sizeof(char *)) - 1; - /* Make sure qemu_binary is not null */ if (!qemu_binary) { fprintf(stderr, "No QEMU binary is set\n"); - exit(1); + return EXIT_FAILURE; } - argv[0] = (char *) qemu_binary; + + strv_append(&argv, "%s", qemu_binary); + strv_concat(&argv, qemu_argv); if (qemu_host_cpu) { - argv[pos++] = "-cpu"; - argv[pos++] = "host"; + strv_append(&argv, "-cpu"); + strv_append(&argv, "host"); } - argv[pos++] = "-kernel"; - argv[pos++] = (char *) kernel_image; - argv[pos++] = "-append"; - argv[pos++] = (char *) cmdline; + strv_append(&argv, "-kernel"); + strv_append(&argv, "%s", kernel_image); + strv_append(&argv, "-append"); + strv_append(&argv, "%s", cmdline); for (i = 0; i < num_devs; i++) { - char *chrdev, *serdev; - - chrdev = alloca(48 + strlen(device_path)); - sprintf(chrdev, "socket,path=%s,id=bt%d", device_path, i); - - serdev = alloca(64); - sprintf(serdev, "virtconsole,chardev=bt%d,name=bt.%d", i, i); - - argv[pos++] = "-chardev"; - argv[pos++] = chrdev; - argv[pos++] = "-device"; - argv[pos++] = serdev; + strv_append(&argv, "-chardev"); + strv_append(&argv, "socket,path=%s,id=bt%d", device_path, i); + strv_append(&argv, "-device"); + strv_append(&argv, "virtconsole,chardev=bt%d,name=bt.%d", i, i); } if (usb_dev) { - argv[pos++] = "-device"; - argv[pos++] = "qemu-xhci"; - argv[pos++] = "-device"; - argv[pos++] = usb_dev; + strv_append(&argv, "-device"); + strv_append(&argv, "qemu-xhci"); + strv_append(&argv, "-device"); + strv_append(&argv, "%s", usb_dev); } if (pcie_dev) { - argv[pos++] = "-device"; - argv[pos++] = pcie_dev; + strv_append(&argv, "-device"); + strv_append(&argv, "%s", pcie_dev); } for (i = 0; i < num_extra_opts; ++i) - argv[pos++] = extra_opts[i]; + strv_append(&argv, "%s", extra_opts[i]); - argv[pos] = NULL; + if (STRV_ERROR(argv)) { + fprintf(stderr, "Failed to build argument list\n"); + return EXIT_FAILURE; + } if (!pcie_dev) { - execve(argv[0], argv, qemu_envp); + execve(argv.strv[0], argv.strv, qemu_envp); return EXIT_FAILURE; } @@ -635,7 +681,7 @@ static int start_qemu(void) } if (pid == 0) { - execve(argv[0], argv, qemu_envp); + execve(argv.strv[0], argv.strv, qemu_envp); exit(EXIT_FAILURE); } -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* RE: test-runner: use virtio-fs by default, functional test speedup 2026-09-12 18:18 [PATCH BlueZ v2 1/4] tools/test-runner: replace alloca() based argv setup Pauli Virtanen @ 2026-09-12 19:17 ` bluez.test.bot 0 siblings, 0 replies; 6+ messages in thread From: bluez.test.bot @ 2026-09-12 19:17 UTC (permalink / raw) To: linux-bluetooth, pav [-- Attachment #1: Type: text/plain, Size: 3496 bytes --] This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/series/1163573/ ---Test result--- Test Summary: CheckPatch FAIL 2.15 seconds GitLint FAIL 1.33 seconds BuildEll PASS 19.81 seconds BluezMake PASS 373.66 seconds MakeCheck PASS 14.08 seconds MakeDistcheck PASS 141.19 seconds CheckValgrind PASS 237.21 seconds CheckSmatch PASS 298.62 seconds bluezmakeextell PASS 97.14 seconds IncrementalBuild PASS 417.21 seconds ScanBuild PASS 1131.54 seconds Details ############################## Test: CheckPatch - FAIL Desc: Run checkpatch.pl script Output: [BlueZ,v2,1/4] tools/test-runner: replace alloca() based argv setup WARNING:PREFER_DEFINED_ATTRIBUTE_MACRO: Prefer __printf(2, 3) over __attribute__((format(printf, 2, 3))) #129: FILE: tools/test-runner.c:81: +static void __attribute__((format(printf, 2, 3))) /github/workspace/src/patch/14810752.patch total: 0 errors, 1 warnings, 202 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/patch/14810752.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [BlueZ,v2,3/4] tools/test-runner: use virtiofsd for filesystem passthrough WARNING:VOLATILE: Use of volatile is usually wrong: see Documentation/process/volatile-considered-harmful.rst #199: FILE: tools/test-runner.c:571: +static volatile sig_atomic_t terminate; WARNING:STATIC_CONST_CHAR_ARRAY: char * array declaration might be better as static const #284: FILE: tools/test-runner.c:656: + const char *cmd[] = { /github/workspace/src/patch/14810754.patch total: 0 errors, 2 warnings, 371 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/patch/14810754.patch has style problems, please review. NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. ############################## Test: GitLint - FAIL Desc: Run gitlint Output: [BlueZ,v2,3/4] tools/test-runner: use virtiofsd for filesystem passthrough 14: B3 Line contains hard tab characters (\t): "real 2m9,736s" 15: B3 Line contains hard tab characters (\t): "user 1m29,570s" 16: B3 Line contains hard tab characters (\t): "sys 0m32,715s" 20: B3 Line contains hard tab characters (\t): "real 1m35,703s" 21: B3 Line contains hard tab characters (\t): "user 0m28,938s" 22: B3 Line contains hard tab characters (\t): "sys 0m7,453s" https://github.com/bluez/bluez/pull/2522 --- Regards, Linux Bluetooth ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-09-12 19:17 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-10 16:48 [PATCH BlueZ 0/2] test-runner: use virtio-fs by default, functional test speedup Pauli Virtanen 2026-09-10 16:48 ` [PATCH BlueZ 1/2] doc: enable virtio-fs in tester kernel configs Pauli Virtanen 2026-09-10 19:30 ` test-runner: use virtio-fs by default, functional test speedup bluez.test.bot 2026-09-10 16:48 ` [PATCH BlueZ 2/2] tools: test-runner: use virtiofsd for filesystem passthrough Pauli Virtanen 2026-09-10 17:16 ` Luiz Augusto von Dentz -- strict thread matches above, loose matches on Subject: below -- 2026-09-12 18:18 [PATCH BlueZ v2 1/4] tools/test-runner: replace alloca() based argv setup Pauli Virtanen 2026-09-12 19:17 ` test-runner: use virtio-fs by default, functional test speedup bluez.test.bot
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.