User-Mode Linux was an experimental alternative way to run the daemon
instead of using qemu. It had many limitations, and UML support in
Linux has been semi-broken for a long time.
This was never supported in RHEL.
See-also:
https://bugzilla.redhat.com/1144197
---
Makefile.am | 22 -
TODO | 5 -
docs/C_SOURCE_FILES | 1 -
docs/guestfs-building.pod | 4 -
docs/guestfs-hacking.pod | 15 -
docs/guestfs-performance.pod | 37 --
fuse/test-fuse-umount-race.sh | 2 -
generator/actions_properties.ml | 3 +-
lib/Makefile.am | 1 -
lib/appliance.c | 16 +-
lib/guestfs-internal.h | 3 +-
lib/guestfs.pod | 89 ---
lib/launch-uml.c | 607 --------------------
lib/launch.c | 9 -
tests/c-api/test-add-libvirt-dom.c | 8 -
tests/disk-labels/test-disk-labels.pl | 5 -
tests/md/test-inspect-fstab.sh | 1 -
tests/mountable/test-mountable-inspect.sh | 1 -
tests/nbd/test-nbd.pl | 5 -
tests/network/test-network.sh | 1 -
tests/qemu/qemu-force-tcg.sh | 2 -
tests/qemu/qemu-snapshot-isolation-qcow2.sh | 2 -
tests/regressions/rhbz1370424.sh | 1 -
tests/regressions/rhbz690819.sh | 2 -
tests/regressions/rhbz975797.sh | 2 -
tests/relative-paths/test-relative-paths.sh | 4 -
tests/rsync/test-rsync.sh | 4 -
tests/test-functions.sh | 2 +-
28 files changed, 4 insertions(+), 850 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index e473ab1147..0260639171 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 6fb11d5ecd..a50f7d73c3 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/9521422ce60578f7196cc8b79...
- - 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 7837120173..30147ef493 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 e46a1222e6..b93a611a6a 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<UML backend|guestfs(3)/BACKEND>.
-
=item curl
Optional. Used by virt-builder for downloads.
diff --git a/docs/guestfs-hacking.pod b/docs/guestfs-hacking.pod
index 1527c4fbd1..5a64740f18 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<make check-uml>
-
-Runs all tests using the User-Mode Linux backend.
-
-As there is no standard location for the User-Mode Linux kernel, you
-I<have> to set C<LIBGUESTFS_HV> to point to the kernel image, eg:
-
- make check-uml LIBGUESTFS_HV=~/d/linux-um/vmlinux
-
-=item C<make check-valgrind-uml>
-
-Runs all tests using the User-Mode Linux backend, under valgrind.
-
-As above, you have to set C<LIBGUESTFS_HV> to point to the kernel.
-
=item C<make check-with-upstream-qemu>
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 b26c6a89bb..acd770a824 100644
--- a/docs/guestfs-performance.pod
+++ b/docs/guestfs-performance.pod
@@ -365,43 +365,6 @@
L<http://rwmj.wordpress.com/2013/02/25/multiple-libguestfs-appliances-...
printf ("%d %.2f\n", $nr_threads, $end_t - $start_t);
}
-=head1 USING USER-MODE LINUX
-
-Since libguestfs 1.24, it has been possible to use the User-Mode Linux
-(uml) backend instead of KVM
-(see L<guestfs(3)/USER-MODE LINUX BACKEND>). This section makes some
-general remarks about this backend, but it is B<highly advisable> 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<http://rwmj.wordpress.com/2013/08/14/performance-of-user-mode-linux-as-a-libguestfs-backend/#content>
-
=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 cfb5fe38f4..d69ffbbf47 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 1ef370d1be..18350a3888 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<linux> or C<vmlinux> 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 5cb7c8e841..144c45588b 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 6b4ee78022..583b6a260d 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 c6432a219f..09ab3ea9e7 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 f9c3d4dc25..bf4238ce93 100644
--- a/lib/guestfs.pod
+++ b/lib/guestfs.pod
@@ -1481,17 +1481,6 @@ URI would be C<libvirt:qemu:///session>
The libvirt backend supports more features, including
hotplugging (see L</HOTPLUGGING>) and sVirt.
-=item C<uml>
-
-Run the User-Mode Linux kernel. The location of the kernel is set
-using C<$LIBGUESTFS_HV> or using the L</guestfs_set_qemu> 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</USER-MODE LINUX BACKEND> below.
-
=back
C<direct> is usually the default backend. However since libguestfs
@@ -1553,84 +1542,6 @@ On Fedora, install C<kernel-debuginfo> for the
C<vmlinux> 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<vmlinux> (or it may be called C<linux>) 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<http://user-mode-linux.sourceforge.net/source.html>
-
-=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<Note:> All ‘make’ commands must have C<ARCH=um> added.
-
- make menuconfig ARCH=um
-
-Make sure any filesystem drivers that you need are compiled into the
-kernel.
-
-B<Currently, it needs a large amount of extra work to get modules
-working>. 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<linux> or C<vmlinux> in the top-level
-directory. This is the UML kernel. You should set C<LIBGUESTFS_HV>
-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 5aec50a578..0000000000
--- 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 <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <inttypes.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/signal.h>
-#include <libintl.h>
-
-#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/u...
- */
-
- /* 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 0675fe98be..2970dc8c45 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 17c349e985..b9669a1bc8 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 17db5e18b9..7bb94cc119 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 3a8d492546..dce340d537 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 7bbc6f1384..bd62eab7da 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 8d1ac385b1..ef10df7bc2 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 55e0f96b1f..144b16319d 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 d540102572..f67b2a281a 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 7a35f3ac4d..9b6424003d 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 c28cf3a16b..f12e160edf 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 <<EOF
-add-domain rhbz1370424 \
diff --git a/tests/regressions/rhbz690819.sh b/tests/regressions/rhbz690819.sh
index 0b790862d4..e6f61d00d3 100755
--- a/tests/regressions/rhbz690819.sh
+++ b/tests/regressions/rhbz690819.sh
@@ -31,8 +31,6 @@ skip_if_arch ppc64
skip_if_arch ppc64le
skip_if_arch s390x
skip_if_backend libvirt
-# UML doesn't support the 'iface' parameter.
-skip_if_backend uml
rm -f rhbz690819.img
diff --git a/tests/regressions/rhbz975797.sh b/tests/regressions/rhbz975797.sh
index 04e8d23de3..c676abfa3c 100755
--- a/tests/regressions/rhbz975797.sh
+++ b/tests/regressions/rhbz975797.sh
@@ -31,8 +31,6 @@ skip_if_arch ppc64
skip_if_arch ppc64le
skip_if_arch s390x
skip_if_backend libvirt
-# UML doesn't support the 'iface' parameter.
-skip_if_backend uml
rm -f rhbz975797-*.img
diff --git a/tests/relative-paths/test-relative-paths.sh
b/tests/relative-paths/test-relative-paths.sh
index ad739142f0..bb27065436 100755
--- a/tests/relative-paths/test-relative-paths.sh
+++ b/tests/relative-paths/test-relative-paths.sh
@@ -21,10 +21,6 @@ set -e
$TEST_FUNCTIONS
skip_if_skipped
-# UML doesn't support qcow2. Conceivably there might be a similar
-# problem with UML COW images which would require a separate test.
-skip_if_backend uml
-
rm -f backing*
rm -f overlay*
rm -f link*
diff --git a/tests/rsync/test-rsync.sh b/tests/rsync/test-rsync.sh
index 02966c0ba1..ab18241698 100755
--- a/tests/rsync/test-rsync.sh
+++ b/tests/rsync/test-rsync.sh
@@ -44,10 +44,6 @@ case "$backend" in
echo "$0: skipping test because host firewall will probably prevent this
test from working"
exit 77
;;
- uml)
- echo "$0: skipping test because networking is not available in the UML
backend"
- exit 77
- ;;
*)
echo "$0: don't know how to get IP address of backend $backend"
exit 77
diff --git a/tests/test-functions.sh b/tests/test-functions.sh
index 8a9c59d0f9..afccfbbdb1 100755
--- a/tests/test-functions.sh
+++ b/tests/test-functions.sh
@@ -54,7 +54,7 @@ skip_if_skipped ()
}
# Skip if the current libguestfs backend is $1.
-# eg. skip_if_backend uml
+# eg. skip_if_backend libvirt
skip_if_backend ()
{
local b="$(guestfish get-backend)"
--
2.35.1