diff --git a/Makefile.am b/Makefile.am index e473ab114..026063917 100644 --- a/Makefile.am +++ b/Makefile.am @@ -302,8 +302,6 @@ check-all: check-valgrind \ check-direct \ check-valgrind-direct \ - check-uml \ - check-valgrind-uml \ check-with-upstream-qemu \ check-with-upstream-libvirt \ check-slow @@ -341,24 +339,6 @@ check-valgrind-direct: check-valgrind-with-appliance: check-valgrind-direct -# Tests which currently fail under UML: -# - blockdev --setro seems to have no effect on /dev/ubd* devices [*] -# - RHBZ#914931: test is sent a SIGTERM, apparently by UML [*] -# - tests/md/test-inspect-fstab-md.sh hangs at various places during the -# test, eg. running mdadm, mounting MD filesystem [*] -# [*] = likely to be a bug in UML itself -SKIP_TESTS_FAILING_IN_UML = \ - SKIP_TEST_BLOCKDEV_GETRO=1 \ - SKIP_TEST_BLOCKDEV_SETRO=1 \ - SKIP_TEST_RHBZ914931=1 \ - SKIP_TEST_INSPECT_FSTAB_MD_SH=1 - -check-uml: - $(MAKE) LIBGUESTFS_BACKEND=uml $(SKIP_TESTS_FAILING_IN_UML) check - -check-valgrind-uml: - $(MAKE) LIBGUESTFS_BACKEND=uml $(SKIP_TESTS_FAILING_IN_UML) check-valgrind - QEMUDIR = $(HOME)/d/qemu QEMUBINARY = $(QEMUDIR)/x86_64-softmmu/qemu-system-x86_64 @@ -499,8 +479,6 @@ help: @echo "make check-valgrind Run a subset of the tests under valgrind." @echo "make check-direct Test using direct backend." @echo "make check-valgrind-direct Test valgrind + direct backend." - @echo "make check-uml Test using User-Mode Linux." - @echo "make check-valgrind-uml Test valgrind + User-Mode Linux." @echo "make check-with-upstream-qemu Test using upstream qemu." @echo "make check-with-upstream-libvirt Test using upstream libvirt." @echo "make check-slow Slow/long-running tests." diff --git a/TODO b/TODO index 6fb11d5ec..a50f7d73c 100644 --- a/TODO +++ b/TODO @@ -532,11 +532,6 @@ virt-builder - /etc/resolv.conf handling works but is best described as a hack: https://github.com/libguestfs/libguestfs/commit/9521422ce60578f7196cc8b7977d998159238c19 - - let's make UML work - + SLIRP is insecure, but we could allow just a bare web proxy which - gets proxied over virtio-serial to the outside world (except - virtio-serial can't be multiplexed) - - sometimes (not always) aug_init takes ages, why? Midnight Commander (mc) extension diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES index 783712017..30147ef49 100644 --- a/docs/C_SOURCE_FILES +++ b/docs/C_SOURCE_FILES @@ -313,7 +313,6 @@ lib/inspect-osinfo.c lib/journal.c lib/launch-direct.c lib/launch-libvirt.c -lib/launch-uml.c lib/launch.c lib/libvirt-auth.c lib/libvirt-domain.c diff --git a/docs/guestfs-building.pod b/docs/guestfs-building.pod index e46a1222e..b93a611a6 100644 --- a/docs/guestfs-building.pod +++ b/docs/guestfs-building.pod @@ -271,10 +271,6 @@ Optional. Used only for testing. Optional. qemu-nbd is used for testing. -=item uml_mkcow - -Optional. For the L. - =item curl Optional. Used by virt-builder for downloads. diff --git a/docs/guestfs-hacking.pod b/docs/guestfs-hacking.pod index 1527c4fbd..5a64740f1 100644 --- a/docs/guestfs-hacking.pod +++ b/docs/guestfs-hacking.pod @@ -649,21 +649,6 @@ using C<./configure --with-default-backend=...> Run a subset of the test suite under valgrind using the default appliance back-end. -=item C - -Runs all tests using the User-Mode Linux backend. - -As there is no standard location for the User-Mode Linux kernel, you -I to set C to point to the kernel image, eg: - - make check-uml LIBGUESTFS_HV=~/d/linux-um/vmlinux - -=item C - -Runs all tests using the User-Mode Linux backend, under valgrind. - -As above, you have to set C to point to the kernel. - =item C Runs all tests using a local qemu binary. It looks for the qemu diff --git a/docs/guestfs-performance.pod b/docs/guestfs-performance.pod index b26c6a89b..acd770a82 100644 --- a/docs/guestfs-performance.pod +++ b/docs/guestfs-performance.pod @@ -365,43 +365,6 @@ L). This section makes some -general remarks about this backend, but it is B to -measure your own workload under UML rather than trusting comments or -intuition. - -=over 4 - -=item * - -UML usually performs the same or slightly slower than KVM, on baremetal. - -=item * - -However UML often performs the same under virtualization as it does on -baremetal, whereas KVM can run much slower under virtualization (since -hardware virt acceleration is not available). - -=item * - -Upload and download is as much as 10 times slower on UML than KVM. -Libguestfs sends this data over the UML emulated serial port, which is -far less efficient than KVM’s virtio-serial. - -=item * - -UML lacks some features (eg. qcow2 support), so it may not be -applicable at all. - -=back - -For some actual figures, see: -L - =head1 TROUBLESHOOTING POOR PERFORMANCE =head2 Ensure hardware virtualization is available diff --git a/fuse/test-fuse-umount-race.sh b/fuse/test-fuse-umount-race.sh index cfb5fe38f..d69ffbbf4 100755 --- a/fuse/test-fuse-umount-race.sh +++ b/fuse/test-fuse-umount-race.sh @@ -25,8 +25,6 @@ $TEST_FUNCTIONS skip_if_skipped "test-fuse.sh" skip_if_skipped skip_unless_phony_guest fedora.img -# UML backend does not support qcow2. -skip_if_backend uml skip_unless_fuse rm -f test.qcow2 test-copy.qcow2 test.pid diff --git a/generator/actions_properties.ml b/generator/actions_properties.ml index 1ef370d1b..18350a388 100644 --- a/generator/actions_properties.ml +++ b/generator/actions_properties.ml @@ -32,8 +32,7 @@ let non_daemon_functions = [ longdesc = "\ Set the hypervisor binary that we will use. The hypervisor depends on the backend, but is usually the location of the -qemu/KVM hypervisor. For the uml backend, it is the location -of the C or C binary. +qemu/KVM hypervisor. The default is chosen when the library was compiled by the configure script. diff --git a/lib/Makefile.am b/lib/Makefile.am index 5cb7c8e84..144c45588 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -97,7 +97,6 @@ libguestfs_la_SOURCES = \ launch.c \ launch-direct.c \ launch-libvirt.c \ - launch-uml.c \ libvirt-auth.c \ libvirt-domain.c \ lpj.c \ diff --git a/lib/appliance.c b/lib/appliance.c index 6b4ee7802..583b6a260 100644 --- a/lib/appliance.c +++ b/lib/appliance.c @@ -281,21 +281,7 @@ build_supermin_appliance (guestfs_h *g, /* Touch the files so they don't get deleted (as they are in /var/tmp). */ (void) utimes (appliance->kernel, NULL); (void) utimes (appliance->initrd, NULL); - - /* Checking backend != "uml" is a big hack. UML encodes the mtime - * of the original backing file (in this case, the appliance) in the - * COW file, and checks it when adding it to the VM. If there are - * multiple threads running and one touches the appliance here, it - * will disturb the mtime and UML will give an error. - * - * We can get rid of this hack as soon as UML fixes the - * ubdN=cow,original parsing bug, since we won't need to run - * uml_mkcow separately, so there is no possible race. - * - * XXX - */ - if (STRNEQ (g->backend, "uml")) - (void) utimes (appliance->image, NULL); + (void) utimes (appliance->image, NULL); return 0; } diff --git a/lib/guestfs-internal.h b/lib/guestfs-internal.h index c6432a219..09ab3ea9e 100644 --- a/lib/guestfs-internal.h +++ b/lib/guestfs-internal.h @@ -292,7 +292,7 @@ struct drive { * it is non-NULL, else consult the original source above. * * Note that the overlay is in a backend-specific format, probably - * different from the source format. eg. qcow2, UML COW. + * different from the source format. eg. qcow2 */ char *overlay; @@ -812,7 +812,6 @@ void guestfs_int_init_direct_backend (void) __attribute__((constructor)); #ifdef HAVE_LIBVIRT_BACKEND void guestfs_int_init_libvirt_backend (void) __attribute__((constructor)); #endif -void guestfs_int_init_uml_backend (void) __attribute__((constructor)); /* qemu.c */ struct qemu_data; diff --git a/lib/guestfs.pod b/lib/guestfs.pod index f9c3d4dc2..bf4238ce9 100644 --- a/lib/guestfs.pod +++ b/lib/guestfs.pod @@ -1481,17 +1481,6 @@ URI would be C The libvirt backend supports more features, including hotplugging (see L) and sVirt. -=item C - -Run the User-Mode Linux kernel. The location of the kernel is set -using C<$LIBGUESTFS_HV> or using the L API (note -that qemu is not involved, we just reuse the same variable in the -handle for convenience). - -User-Mode Linux can be much faster, simpler and more lightweight than -using a full-blown virtual machine, but it also has some shortcomings. -See L below. - =back C is usually the default backend. However since libguestfs @@ -1553,84 +1542,6 @@ On Fedora, install C for the C file (containing symbols). Make sure the symbols precisely match the kernel being used. -=head2 USER-MODE LINUX BACKEND - -Setting the following environment variables (or the equivalent in the -API) selects the User-Mode Linux backend: - - export LIBGUESTFS_BACKEND=uml - export LIBGUESTFS_HV=/path/to/vmlinux - -C (or it may be called C) is the Linux binary, -compiled to run as a userspace process. Note that we reuse the qemu -variable in the handle for convenience; qemu is not involved. - -User-Mode Linux can be faster and more lightweight than running a -full-blown virtual machine as the backend (especially if you are -already running libguestfs in a virtual machine or cloud instance), -but it also has some shortcomings compared to the usual qemu/KVM-based -backend. - -=head3 BUILDING USER-MODE LINUX FROM SOURCE - -Your Linux distro may provide UML in which case you can ignore this -section. - -These instructions are adapted from: -L - -=over 4 - -=item 1. Check out Linux sources - -Clone the Linux git repository or download the Linux source tarball. - -=item 2. Configure the kernel - -B All ‘make’ commands must have C added. - - make menuconfig ARCH=um - -Make sure any filesystem drivers that you need are compiled into the -kernel. - -B. It’s recommended that you disable module support in the -kernel configuration, which will cause everything to be compiled into -the image. - -=item 3. Build the kernel - - make ARCH=um - -This will leave a file called C or C in the top-level -directory. This is the UML kernel. You should set C -to point to this file. - -=back - -=head3 USER-MODE LINUX DIFFERENCES FROM KVM - -=over 4 - -=item UML only supports raw-format images - -Only plain raw-format images will work. No qcow2, no backing files. - -=item UML does not support any remote drives - -No NBD, etc. - -=item UML only works on ix86 and x86-64 - -=item UML is experimental - -In particular, support for UML in libguestfs depends on support for -UML in the upstream kernel. If UML was ever removed from the upstream -Linux kernel, then we might remove it from libguestfs too. - -=back - =head2 ABI GUARANTEE We guarantee the libguestfs ABI (binary interface), for public, diff --git a/lib/launch-uml.c b/lib/launch-uml.c deleted file mode 100644 index 5aec50a57..000000000 --- a/lib/launch-uml.c +++ /dev/null @@ -1,607 +0,0 @@ -/* libguestfs - * Copyright (C) 2009-2020 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cloexec.h" - -#include "guestfs.h" -#include "guestfs-internal.h" -#include "guestfs_protocol.h" - -/* Per-handle data. */ -struct backend_uml_data { - pid_t pid; /* vmlinux PID. */ - pid_t recoverypid; /* Recovery process PID. */ - -#define UML_UMID_LEN 16 - char umid[UML_UMID_LEN+1]; /* umid=<...> unique ID. */ -}; - -static void print_vmlinux_command_line (guestfs_h *g, char **argv); - -/* Run uml_mkcow to create a COW overlay. */ -static char * -make_cow_overlay (guestfs_h *g, const char *original) -{ - CLEANUP_CMD_CLOSE struct command *cmd = guestfs_int_new_command (g); - char *overlay; - int r; - - overlay = guestfs_int_make_temp_path (g, "overlay", "qcow2"); - if (!overlay) - return NULL; - - guestfs_int_cmd_add_arg (cmd, "uml_mkcow"); - guestfs_int_cmd_add_arg (cmd, overlay); - guestfs_int_cmd_add_arg (cmd, original); - r = guestfs_int_cmd_run (cmd); - if (r == -1) { - free (overlay); - return NULL; - } - if (!WIFEXITED (r) || WEXITSTATUS (r) != 0) { - guestfs_int_external_command_failed (g, r, "uml_mkcow", original); - free (overlay); - return NULL; - } - - return overlay; -} - -static char * -create_cow_overlay_uml (guestfs_h *g, void *datav, struct drive *drv) -{ - return make_cow_overlay (g, drv->src.u.path); -} - -/* Test for features which are not supported by the UML backend. - * Possibly some of these should just be warnings, not errors. - */ -static bool -uml_supported (guestfs_h *g) -{ - size_t i; - struct drive *drv; - - if (g->enable_network) { - error (g, _("uml backend does not support networking")); - return false; - } - if (g->smp > 1) { - error (g, _("uml backend does not support SMP")); - return false; - } - - ITER_DRIVES (g, i, drv) { - if (drv->src.protocol != drive_protocol_file) { - error (g, _("uml backend does not support remote drives")); - return false; - } - if (drv->src.format && STRNEQ (drv->src.format, "raw")) { - error (g, _("uml backend does not support non-raw-format drives")); - return false; - } - if (drv->iface) { - error (g, - _("uml backend does not support drives with ‘iface’ parameter")); - return false; - } - if (drv->disk_label) { - error (g, - _("uml backend does not support drives with ‘label’ parameter")); - return false; - } - /* Note that discard == "besteffort" is fine. */ - if (drv->discard == discard_enable) { - error (g, - _("uml backend does not support drives with ‘discard’ parameter set to ‘enable’")); - return false; - } - if (drv->blocksize) { - error (g, - _("uml backend does not support drives with ‘blocksize’ parameter")); - return false; - } - } - - return true; -} - -static int -launch_uml (guestfs_h *g, void *datav, const char *arg) -{ - struct backend_uml_data *data = datav; - CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (cmdline); - int console_sock = -1, daemon_sock = -1; - int r; - int csv[2], dsv[2]; - CLEANUP_FREE char *kernel = NULL, *initrd = NULL, *appliance = NULL; - int has_appliance_drive; - CLEANUP_FREE char *appliance_cow = NULL; - uint32_t size; - CLEANUP_FREE void *buf = NULL; - struct drive *drv; - size_t i; - struct hv_param *hp; - char *term = getenv ("TERM"); - - if (!uml_supported (g)) - return -1; - - if (!g->nr_drives) { - error (g, _("you must call guestfs_add_drive before guestfs_launch")); - return -1; - } - - /* Assign a random unique ID to this run. */ - if (guestfs_int_random_string (data->umid, UML_UMID_LEN) == -1) { - perrorf (g, "guestfs_int_random_string"); - return -1; - } - - /* Locate and/or build the appliance. */ - if (guestfs_int_build_appliance (g, &kernel, &initrd, &appliance) == -1) - return -1; - has_appliance_drive = appliance != NULL; - - /* Create COW overlays for the appliance. Note that the documented - * syntax ubd0=cow,orig does not work since kernel 3.3. See: - * http://thread.gmane.org/gmane.linux.uml.devel/13556 - */ - if (has_appliance_drive) { - appliance_cow = make_cow_overlay (g, appliance); - if (!appliance_cow) - goto cleanup0; - } - - /* The socket that the daemon will talk to us on. - */ - if (socketpair (AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, dsv) == -1) { - perrorf (g, "socketpair"); - goto cleanup0; - } - - /* The console socket. */ - if (!g->direct_mode) { - if (socketpair (AF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC, 0, csv) == -1) { - perrorf (g, "socketpair"); - close (dsv[0]); - close (dsv[1]); - goto cleanup0; - } - } - - /* Construct the vmlinux command line. We have to do this before - * forking, because after fork we are not allowed to use - * non-signal-safe functions such as malloc. - */ -#define ADD_CMDLINE(str) \ - guestfs_int_add_string (g, &cmdline, (str)) -#define ADD_CMDLINE_PRINTF(fs,...) \ - guestfs_int_add_sprintf (g, &cmdline, (fs), ##__VA_ARGS__) - - ADD_CMDLINE (g->hv); - - /* Give this instance a unique random ID. */ - ADD_CMDLINE_PRINTF ("umid=%s", data->umid); - - /* Set memory size. */ - ADD_CMDLINE_PRINTF ("mem=%dM", g->memsize); - - /* vmlinux appears to ignore this, but let's add it anyway. */ - ADD_CMDLINE_PRINTF ("initrd=%s", initrd); - - /* Make sure our appliance init script runs first. */ - ADD_CMDLINE ("init=/init"); - - /* This tells the /init script not to reboot at the end. */ - ADD_CMDLINE ("guestfs_noreboot=1"); - - /* Root filesystem should be mounted read-write (default seems to - * be "ro"). - */ - ADD_CMDLINE ("rw"); - - /* See also guestfs_int_appliance_command_line. */ - if (g->verbose) - ADD_CMDLINE ("guestfs_verbose=1"); - - ADD_CMDLINE ("panic=1"); - - ADD_CMDLINE_PRINTF ("TERM=%s", term ? term : "linux"); - - if (g->selinux) - ADD_CMDLINE ("selinux=1 enforcing=0"); - else - ADD_CMDLINE ("selinux=0"); - - /* XXX This isn't quite right. Multiple append args won't work. */ - if (g->append) - ADD_CMDLINE (g->append); - - /* Add the drives. */ - ITER_DRIVES (g, i, drv) { - if (!drv->overlay) - ADD_CMDLINE_PRINTF ("ubd%zu=%s", i, drv->src.u.path); - else - ADD_CMDLINE_PRINTF ("ubd%zu=%s", i, drv->overlay); - } - - /* Add the ext2 appliance drive (after all the drives). */ - if (has_appliance_drive) { - char drv_name[64] = "ubd"; - guestfs_int_drive_name (g->nr_drives, &drv_name[3]); - - ADD_CMDLINE_PRINTF ("ubd%zu=%s", g->nr_drives, appliance_cow); - ADD_CMDLINE_PRINTF ("root=/dev/%s", drv_name); - } - - /* Create the daemon socket. */ - ADD_CMDLINE_PRINTF ("ssl3=fd:%d", dsv[1]); - ADD_CMDLINE ("guestfs_channel=/dev/ttyS3"); - - /* Add any vmlinux parameters. */ - for (hp = g->hv_params; hp; hp = hp->next) { - ADD_CMDLINE (hp->hv_param); - if (hp->hv_value) - ADD_CMDLINE (hp->hv_value); - } - - /* Finish off the command line. */ - guestfs_int_end_stringsbuf (g, &cmdline); - - r = fork (); - if (r == -1) { - perrorf (g, "fork"); - if (!g->direct_mode) { - close (csv[0]); - close (csv[1]); - } - close (dsv[0]); - close (dsv[1]); - goto cleanup0; - } - - if (r == 0) { /* Child (vmlinux). */ - /* Set up the daemon socket for the child. */ - close (dsv[0]); - set_cloexec_flag (dsv[1], 0); /* so it doesn't close across exec */ - - if (!g->direct_mode) { - /* Set up stdin, stdout, stderr. */ - close (0); - close (1); - close (csv[0]); - - /* We set the FD_CLOEXEC flag on the socket above, but now (in - * the child) it's safe to unset this flag so vmlinux can use the - * socket. - */ - set_cloexec_flag (csv[1], 0); - - /* Stdin. */ - if (dup (csv[1]) == -1) { - dup_failed: - perror ("dup failed"); - _exit (EXIT_FAILURE); - } - /* Stdout. */ - if (dup (csv[1]) == -1) - goto dup_failed; - - /* Send stderr to the pipe as well. */ - close (2); - if (dup (csv[1]) == -1) - goto dup_failed; - - close (csv[1]); - - /* RHBZ#1123007 */ - close_file_descriptors (fd > 2 && fd != dsv[1]); - } - - /* RHBZ#1460338. */ - guestfs_int_unblock_sigterm (); - - /* Dump the command line (after setting up stderr above). */ - if (g->verbose) - print_vmlinux_command_line (g, cmdline.argv); - - /* Put vmlinux in a new process group. */ - if (g->pgroup) - setpgid (0, 0); - - setenv ("LC_ALL", "C", 1); - - execv (g->hv, cmdline.argv); /* Run vmlinux. */ - perror (g->hv); - _exit (EXIT_FAILURE); - } - - /* Parent (library). */ - data->pid = r; - - /* Fork the recovery process off which will kill vmlinux if the - * parent process fails to do so (eg. if the parent segfaults). - */ - data->recoverypid = -1; - if (g->recovery_proc) { - r = fork (); - if (r == 0) { - struct sigaction sa; - pid_t vmlinux_pid = data->pid; - pid_t parent_pid = getppid (); - - /* Remove all signal handlers. See the justification here: - * https://www.redhat.com/archives/libvir-list/2008-August/msg00303.html - * We don't mask signal handlers yet, so this isn't completely - * race-free, but better than not doing it at all. - */ - memset (&sa, 0, sizeof sa); - sa.sa_handler = SIG_DFL; - sa.sa_flags = 0; - sigemptyset (&sa.sa_mask); - for (i = 1; i < NSIG; ++i) - sigaction (i, &sa, NULL); - - /* Close all other file descriptors. This ensures that we don't - * hold open (eg) pipes from the parent process. - */ - close_file_descriptors (1); - - /* RHBZ#1460338 */ - guestfs_int_unblock_sigterm (); - - /* It would be nice to be able to put this in the same process - * group as vmlinux (ie. setpgid (0, vmlinux_pid)). However - * this is not possible because we don't have any guarantee here - * that the vmlinux process has started yet. - */ - if (g->pgroup) - setpgid (0, 0); - - /* Writing to argv is hideously complicated and error prone. See: - * http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/misc/ps_status.c;hb=HEAD - */ - - /* Loop around waiting for one or both of the other processes to - * disappear. It's fair to say this is very hairy. The PIDs that - * we are looking at might be reused by another process. We are - * effectively polling. Is the cure worse than the disease? - */ - for (;;) { - if (kill (vmlinux_pid, 0) == -1) - /* vmlinux's gone away, we aren't needed */ - _exit (EXIT_SUCCESS); - if (kill (parent_pid, 0) == -1) { - /* Parent's gone away, vmlinux still around, so kill vmlinux. */ - kill (data->pid, SIGKILL); - _exit (EXIT_SUCCESS); - } - sleep (2); - } - } - - /* Don't worry, if the fork failed, this will be -1. The recovery - * process isn't essential. - */ - data->recoverypid = r; - } - - if (!g->direct_mode) { - /* Close the other end of the console socketpair. */ - close (csv[1]); - - console_sock = csv[0]; /* stdin of child */ - csv[0] = -1; - } - - daemon_sock = dsv[0]; - close (dsv[1]); - dsv[0] = -1; - - g->state = LAUNCHING; - - /* Wait for vmlinux to start and to connect back to us via - * virtio-serial and send the GUESTFS_LAUNCH_FLAG message. - */ - g->conn = - guestfs_int_new_conn_socket_connected (g, daemon_sock, console_sock); - if (!g->conn) - goto cleanup1; - - /* g->conn now owns these sockets. */ - daemon_sock = console_sock = -1; - - /* We now have to wait for vmlinux to start up, the daemon to start - * running, and for it to send the GUESTFS_LAUNCH_FLAG to us. - */ - r = guestfs_int_recv_from_daemon (g, &size, &buf); - - if (r == -1) { - guestfs_int_launch_failed_error (g); - goto cleanup1; - } - - if (size != GUESTFS_LAUNCH_FLAG) { - guestfs_int_launch_failed_error (g); - goto cleanup1; - } - - debug (g, "appliance is up"); - - /* This is possible in some really strange situations, such as - * guestfsd starts up OK but then vmlinux immediately exits. Check - * for it because the caller is probably expecting to be able to - * send commands after this function returns. - */ - if (g->state != READY) { - error (g, _("vmlinux launched and contacted daemon, but state != READY")); - goto cleanup1; - } - - if (has_appliance_drive) - guestfs_int_add_dummy_appliance_drive (g); - - return 0; - - cleanup1: - if (!g->direct_mode && csv[0] >= 0) - close (csv[0]); - if (dsv[0] >= 0) - close (dsv[0]); - if (data->pid > 0) kill (data->pid, SIGKILL); - if (data->recoverypid > 0) kill (data->recoverypid, SIGKILL); - if (data->pid > 0) guestfs_int_waitpid_noerror (data->pid); - if (data->recoverypid > 0) guestfs_int_waitpid_noerror (data->recoverypid); - data->pid = 0; - data->recoverypid = 0; - memset (&g->launch_t, 0, sizeof g->launch_t); - - cleanup0: - if (daemon_sock >= 0) - close (daemon_sock); - if (console_sock >= 0) - close (console_sock); - if (g->conn) { - g->conn->ops->free_connection (g, g->conn); - g->conn = NULL; - } - g->state = CONFIG; - return -1; -} - -/* This is called from the forked subprocess just before vmlinux runs, - * so it can just print the message straight to stderr, where it will - * be picked up and funnelled through the usual appliance event API. - */ -static void -print_vmlinux_command_line (guestfs_h *g, char **argv) -{ - size_t i = 0; - int needs_quote; - - struct timeval tv; - gettimeofday (&tv, NULL); - fprintf (stderr, "[%05" PRIi64 "ms] ", - guestfs_int_timeval_diff (&g->launch_t, &tv)); - - while (argv[i]) { - if (i > 0) fputc (' ', stderr); - - /* Does it need shell quoting? This only deals with simple cases. */ - needs_quote = strcspn (argv[i], " ") != strlen (argv[i]); - - if (needs_quote) fputc ('\'', stderr); - fprintf (stderr, "%s", argv[i]); - if (needs_quote) fputc ('\'', stderr); - i++; - } - - fputc ('\n', stderr); -} - -static int -shutdown_uml (guestfs_h *g, void *datav, int check_for_errors) -{ - struct backend_uml_data *data = datav; - int ret = 0; - int status; - - /* Signal vmlinux to shutdown cleanly, and kill the recovery process. */ - if (data->pid > 0) { - debug (g, "sending SIGTERM to process %d", data->pid); - kill (data->pid, SIGTERM); - } - if (data->recoverypid > 0) kill (data->recoverypid, 9); - - /* Wait for subprocess(es) to exit. */ - if (data->pid > 0) { - if (guestfs_int_waitpid (g, data->pid, &status, "vmlinux") == -1) - ret = -1; - /* Note it's normal for the pre-3.11 vmlinux process to exit with - * status "killed by signal 15" (where 15 == SIGTERM). Post 3.11 - * the exit status can normally be 1. - * - * So don't consider those to be an error. - */ - else if (!(WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM) && - !(WIFEXITED (status) && WEXITSTATUS (status) == 0) && - !(WIFEXITED (status) && WEXITSTATUS (status) == 1)) { - guestfs_int_external_command_failed (g, status, g->hv, NULL); - ret = -1; - } - } - if (data->recoverypid > 0) guestfs_int_waitpid_noerror (data->recoverypid); - - data->pid = data->recoverypid = 0; - - return ret; -} - -static int -get_pid_uml (guestfs_h *g, void *datav) -{ - struct backend_uml_data *data = datav; - - if (data->pid > 0) - return data->pid; - else { - error (g, "get_pid: no vmlinux subprocess"); - return -1; - } -} - -/* UML appears to use a single major, and puts ubda at minor 0 with - * each partition at minors 1-15, ubdb at minor 16, etc. So the - * maximum is 256/16 = 16. However one disk is used by the appliance, - * so it's one less than this. I tested both 15 & 16 disks, and found - * that 15 worked and 16 failed. - */ -static int -max_disks_uml (guestfs_h *g, void *datav) -{ - return 15; -} - -static struct backend_ops backend_uml_ops = { - .data_size = sizeof (struct backend_uml_data), - .create_cow_overlay = create_cow_overlay_uml, - .launch = launch_uml, - .shutdown = shutdown_uml, - .get_pid = get_pid_uml, - .max_disks = max_disks_uml, -}; - -void -guestfs_int_init_uml_backend (void) -{ - guestfs_int_register_backend ("uml", &backend_uml_ops); -} diff --git a/lib/launch.c b/lib/launch.c index 0675fe98b..2970dc8c4 100644 --- a/lib/launch.c +++ b/lib/launch.c @@ -284,14 +284,6 @@ guestfs_impl_config (guestfs_h *g, { struct hv_param *hp; - /* - XXX For qemu this made sense, but not for uml. - if (hv_param[0] != '-') { - error (g, _("parameter must begin with '-' character")); - return -1; - } - */ - /* A bit fascist, but the user will probably break the extra * parameters that we add if they try to set any of these. */ @@ -431,5 +423,4 @@ guestfs_int_force_load_backends[] = { #ifdef HAVE_LIBVIRT_BACKEND guestfs_int_init_libvirt_backend, #endif - guestfs_int_init_uml_backend, }; diff --git a/tests/c-api/test-add-libvirt-dom.c b/tests/c-api/test-add-libvirt-dom.c index 17c349e98..b9669a1bc 100644 --- a/tests/c-api/test-add-libvirt-dom.c +++ b/tests/c-api/test-add-libvirt-dom.c @@ -73,7 +73,6 @@ main (int argc, char *argv[]) virDomainPtr dom; virErrorPtr err; int r; - char *backend; char cwd[1024]; FILE *fp; char libvirt_uri[sizeof cwd + 64]; @@ -86,13 +85,6 @@ main (int argc, char *argv[]) if (g == NULL) error (EXIT_FAILURE, errno, "guestfs_create"); - backend = guestfs_get_backend (g); - if (STREQ (backend, "uml")) { - free (backend); - error (77, 0, "test skipped because UML backend does not support qcow2"); - } - free (backend); - /* Create the libvirt XML and test images in the current * directory. */ diff --git a/tests/disk-labels/test-disk-labels.pl b/tests/disk-labels/test-disk-labels.pl index 17db5e18b..7bb94cc11 100755 --- a/tests/disk-labels/test-disk-labels.pl +++ b/tests/disk-labels/test-disk-labels.pl @@ -25,11 +25,6 @@ use Sys::Guestfs; exit 77 if $ENV{SKIP_TEST_DISK_LABELS_PL}; -if (Sys::Guestfs->new()->get_backend() eq "uml") { - print "$0: test skipped because UML backend does not support disk labels\n"; - exit 77 -} - my $g = Sys::Guestfs->new (); # Add two drives. diff --git a/tests/md/test-inspect-fstab.sh b/tests/md/test-inspect-fstab.sh index 3a8d49254..dce340d53 100755 --- a/tests/md/test-inspect-fstab.sh +++ b/tests/md/test-inspect-fstab.sh @@ -24,7 +24,6 @@ set -e $TEST_FUNCTIONS skip_because "device name hints are broken" ;# XXX Fix before 1.38 skip_if_skipped -skip_if_backend uml skip_unless_phony_guest fedora.img canonical="sed -r s,/dev/[abce-ln-z]+d,/dev/sd,g" diff --git a/tests/mountable/test-mountable-inspect.sh b/tests/mountable/test-mountable-inspect.sh index 7bbc6f138..bd62eab7d 100755 --- a/tests/mountable/test-mountable-inspect.sh +++ b/tests/mountable/test-mountable-inspect.sh @@ -20,7 +20,6 @@ set -e $TEST_FUNCTIONS skip_if_skipped -skip_if_backend uml skip_unless_feature_available btrfs canonical="sed s,/dev/vd,/dev/sd,g" diff --git a/tests/nbd/test-nbd.pl b/tests/nbd/test-nbd.pl index 8d1ac385b..ef10df7bc 100755 --- a/tests/nbd/test-nbd.pl +++ b/tests/nbd/test-nbd.pl @@ -27,11 +27,6 @@ END { kill 15, $pid if $pid > 0 }; exit 77 if $ENV{SKIP_TEST_NBD_PL}; -if (Sys::Guestfs->new()->get_backend() eq "uml") { - print "$0: test skipped because UML backend does not support NBD\n"; - exit 77 -} - # Check we have qemu-nbd. if (system ("qemu-nbd --help >/dev/null 2>&1") != 0) { print "$0: test skipped because qemu-nbd program not found\n"; diff --git a/tests/network/test-network.sh b/tests/network/test-network.sh index 55e0f96b1..144b16319 100755 --- a/tests/network/test-network.sh +++ b/tests/network/test-network.sh @@ -24,6 +24,5 @@ set -e $TEST_FUNCTIONS skip_if_skipped -skip_if_backend uml guestfish --network -a /dev/null run diff --git a/tests/qemu/qemu-force-tcg.sh b/tests/qemu/qemu-force-tcg.sh index d54010257..f67b2a281 100755 --- a/tests/qemu/qemu-force-tcg.sh +++ b/tests/qemu/qemu-force-tcg.sh @@ -20,8 +20,6 @@ $TEST_FUNCTIONS skip_if_skipped -# Only applicable if the backend uses qemu. -skip_if_backend uml set -e diff --git a/tests/qemu/qemu-snapshot-isolation-qcow2.sh b/tests/qemu/qemu-snapshot-isolation-qcow2.sh index 7a35f3ac4..9b6424003 100755 --- a/tests/qemu/qemu-snapshot-isolation-qcow2.sh +++ b/tests/qemu/qemu-snapshot-isolation-qcow2.sh @@ -24,8 +24,6 @@ set -e $TEST_FUNCTIONS skip_if_skipped -# UML backend doesn't support qcow2 format. -skip_if_backend uml f=isolation-qcow2.img rm -f $f diff --git a/tests/regressions/rhbz1370424.sh b/tests/regressions/rhbz1370424.sh index c28cf3a16..f12e160ed 100755 --- a/tests/regressions/rhbz1370424.sh +++ b/tests/regressions/rhbz1370424.sh @@ -24,7 +24,6 @@ set -e $TEST_FUNCTIONS skip_if_skipped -skip_if_backend uml guestfish <