Matthew Booth
2010-Aug-26 11:11 UTC
[Libguestfs] [REPOST] guestfsd core capture, and virt-rescue clean shutdown
This is a repost of a previously posted set. It's been updated following review comments. [PATCH 1/4] Add a core_pattern debug command Added missing return statements. [PATCH 2/4] Call sync after guestfsd exits Remove redundant sleep 1; sync [PATCH 3/4] Shut down the appliance cleanly [PATCH 4/4] Ignore launch() error in virt-rescue These were previously 2 patches. They are otherwise unchanged.
Matthew Booth
2010-Aug-26 11:11 UTC
[Libguestfs] [PATCH 1/4] Add a core_pattern debug command
This adds a new debug command, core_pattern, which writes a new pattern for
coredump files to the appliance kernel, and sets the daemon's hard and soft
core
limits to infinity.
---
daemon/debug.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/daemon/debug.c b/daemon/debug.c
index 0867ccd..37d5237 100644
--- a/daemon/debug.c
+++ b/daemon/debug.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
+#include <sys/resource.h>
#include "../src/guestfs_protocol.h"
#include "daemon.h"
@@ -52,6 +53,7 @@ static char *debug_ls (const char *subcmd, int argc, char
*const *const argv);
static char *debug_ll (const char *subcmd, int argc, char *const *const argv);
static char *debug_segv (const char *subcmd, int argc, char *const *const
argv);
static char *debug_sh (const char *subcmd, int argc, char *const *const argv);
+static char *debug_core_pattern (const char *subcmd, int argc, char *const
*const argv);
static struct cmd cmds[] = {
{ "help", debug_help },
@@ -61,6 +63,7 @@ static struct cmd cmds[] = {
{ "ll", debug_ll },
{ "segv", debug_segv },
{ "sh", debug_sh },
+ { "core_pattern", debug_core_pattern },
{ NULL, NULL }
};
#endif
@@ -338,6 +341,49 @@ debug_ll (const char *subcmd, int argc, char *const *const
argv)
return out;
}
+/* Enable core dumping to the given core pattern.
+ * Note that this pattern is relative to any chroot of the process which
+ * crashes. This means that if you want to write the core file to the
guest's
+ * storage the pattern must start with /sysroot only if the command which
+ * crashes doesn't chroot.
+ */
+static char *
+debug_core_pattern (const char *subcmd, int argc, char *const *const argv)
+{
+ if (argc < 1) {
+ reply_with_error ("core_pattern: expecting a core pattern");
+ }
+
+ const char *pattern = argv[0];
+ const size_t pattern_len = strlen(pattern);
+
+#define CORE_PATTERN "/proc/sys/kernel/core_pattern"
+ int fd = open (CORE_PATTERN, O_WRONLY);
+ if (fd == -1) {
+ reply_with_error ("open: " CORE_PATTERN);
+ return NULL;
+ }
+ if (write (fd, pattern, pattern_len) < (ssize_t) pattern_len) {
+ reply_with_error ("write: " CORE_PATTERN);
+ return NULL;
+ }
+ if (close (fd) == -1) {
+ reply_with_error ("close: " CORE_PATTERN);
+ return NULL;
+ }
+
+ struct rlimit limit = {
+ .rlim_cur = RLIM_INFINITY,
+ .rlim_max = RLIM_INFINITY
+ };
+ if (setrlimit (RLIMIT_CORE, &limit) == -1) {
+ reply_with_error ("setrlimit (RLIMIT_CORE)");
+ return NULL;
+ }
+
+ return strdup("ok");
+}
+
#endif /* ENABLE_DEBUG_COMMAND */
#if ENABLE_DEBUG_COMMAND
--
1.7.2.2
Matthew Booth
2010-Aug-26 11:11 UTC
[Libguestfs] [PATCH 2/4] Call sync after guestfsd exits
Core files are not reliably written to disk if guestfsd dumps core. This patch makes libguestfs do the same appliance cleanup for guestfsd and virt-rescue, which seems to fix the matter. It also removes a redundant sleep and additional sync when exiting virt-rescue. --- appliance/init | 45 ++++++++++++++++++++++++--------------------- 1 files changed, 24 insertions(+), 21 deletions(-) diff --git a/appliance/init b/appliance/init index 6aeea0c..90da1cb 100755 --- a/appliance/init +++ b/appliance/init @@ -88,27 +88,30 @@ if grep -sq guestfs_verbose=1 /proc/cmdline; then fi if ! grep -sq guestfs_rescue=1 /proc/cmdline; then - exec guestfsd -f + # The host will kill qemu abruptly if guestfsd shuts down normally + guestfsd -f + + # Otherwise we try to clean up gracefully. For example, this ensures that a + # core dump generated by the guest daemon will be written to disk. +else + # Use appliance in rescue mode, also used by the virt-rescue command. + eval $(grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline) + PS1='><rescue> ' + export TERM PS1 + echo + echo "------------------------------------------------------------" + echo + echo "Welcome to virt-rescue, the libguestfs rescue shell." + echo + echo "Note: The contents of / are the rescue appliance." + echo "You have to mount the guest's partitions under /sysroot" + echo "before you can examine them." + echo + bash -i + echo + echo "virt-rescue: Syncing the disk now before exiting ..." + echo "(Don't worry if you see a 'Kernel panic' message below)" + echo fi -# Use appliance in rescue mode, also used by the virt-rescue command. -eval $(grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline) -PS1='><rescue> ' -export TERM PS1 -echo -echo "------------------------------------------------------------" -echo -echo "Welcome to virt-rescue, the libguestfs rescue shell." -echo -echo "Note: The contents of / are the rescue appliance." -echo "You have to mount the guest's partitions under /sysroot" -echo "before you can examine them." -echo -bash -i -echo -echo "virt-rescue: Syncing the disk now before exiting ..." -echo "(Don't worry if you see a 'Kernel panic' message below)" -echo -sync -sleep 1 sync -- 1.7.2.2
Matthew Booth
2010-Aug-26 11:12 UTC
[Libguestfs] [PATCH 3/4] Shut down the appliance cleanly
When guestfsd exits, or the user exits the virt-rescue shell, the init script
exits which causes the kernel to panic. This isn't really a functional
issue, as
all useful work is done by this point. However, it does cause virt-rescue to
display an unsightly error message.
This patch adds a new utility, guestfs_poweroff, to the appliance. This powers
off (reboots really: read the comment) the appliance, preventing init from
exiting, and therefore the kernel panic.
---
.gitignore | 1 +
appliance/Makefile.am | 6 ++++--
appliance/debian/modules/y0_install-guestfsd | 2 ++
appliance/guestfs_poweroff.c | 14 ++++++++++++++
appliance/init | 2 +-
appliance/update.sh.in | 4 ++++
po/POTFILES.in | 1 +
7 files changed, 27 insertions(+), 3 deletions(-)
create mode 100644 appliance/guestfs_poweroff.c
diff --git a/.gitignore b/.gitignore
index 094acb3..abd88bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ appliance/debian/debirf-libguestfs*.cgz
appliance/debian/root/
appliance/debian/vmlinuz-*
appliance/debian/debirf.conf
+appliance/guestfs_poweroff
appliance/initramfs.*.img
appliance/kmod.whitelist
appliance/make.sh
diff --git a/appliance/Makefile.am b/appliance/Makefile.am
index bbf3c24..ccf7907 100644
--- a/appliance/Makefile.am
+++ b/appliance/Makefile.am
@@ -46,6 +46,8 @@ superminfs_DATA = \
supermin.d/hostfiles
endif
+noinst_PROGRAMS = guestfs_poweroff
+
# Don't change these names - they must be the same as in '*.sh'
scripts.
INITRAMFSIMG = initramfs.$(REPO).$(host_cpu).img
VMLINUZ = vmlinuz.$(REPO).$(host_cpu)
@@ -67,7 +69,7 @@ make.sh: make.sh.in
chmod +x $@-t
mv $@-t $@
-$(INITRAMFSIMG): $(top_builddir)/initramfs/fakeroot.log
$(top_builddir)/daemon/guestfsd init update.sh
+$(INITRAMFSIMG): $(top_builddir)/initramfs/fakeroot.log
$(top_builddir)/daemon/guestfsd init guestfs_poweroff update.sh
rm -f $@
bash update.sh
touch $@
@@ -99,7 +101,7 @@ supermin.d/daemon.img: $(INITRAMFSIMG)
mkdir -p supermin.d
rm -f $@ $@-t
(cd $(top_builddir)/initramfs && \
- echo -e "sbin\nsbin/guestfsd" | cpio --quiet -o -H newc ) >
$@-t
+ echo -e "sbin\nsbin/guestfsd\nsbin/guestfs_poweroff" | cpio
--quiet -o -H newc ) > $@-t
mv $@-t $@
endif
diff --git a/appliance/debian/modules/y0_install-guestfsd
b/appliance/debian/modules/y0_install-guestfsd
index 2d895a0..c2b812a 100755
--- a/appliance/debian/modules/y0_install-guestfsd
+++ b/appliance/debian/modules/y0_install-guestfsd
@@ -37,4 +37,6 @@ rm -rf "$DEBIRF_ROOT"/usr/share/man/
# Install the actual appliance:
echo $PWD
install -o root -g root -m 0755 ../daemon/guestfsd
"$DEBIRF_ROOT"/sbin/guestfsd
+install -o root -g root -m 0755 ../appliance/guestfs_poweroff \
+ "$DEBIRF_ROOT"/sbin/guestfs_poweroff
install -o root -g root -m 0755 init "$DEBIRF_ROOT"/sbin/init
diff --git a/appliance/guestfs_poweroff.c b/appliance/guestfs_poweroff.c
new file mode 100644
index 0000000..7e18839
--- /dev/null
+++ b/appliance/guestfs_poweroff.c
@@ -0,0 +1,14 @@
+#include <stdio.h>
+#include <sys/reboot.h>
+
+int main(int argc, char **argv)
+{
+ /* We actually hard reboot here rather than power off. For some reason
+ * reboot causes the qemu process to die, whereas poweroff doesn't.
+ *
+ * This should not return */
+ reboot(RB_AUTOBOOT);
+
+ perror("Power off failed");
+ return 1;
+}
diff --git a/appliance/init b/appliance/init
index 90da1cb..4ed93b8 100755
--- a/appliance/init
+++ b/appliance/init
@@ -110,8 +110,8 @@ else
bash -i
echo
echo "virt-rescue: Syncing the disk now before exiting ..."
- echo "(Don't worry if you see a 'Kernel panic' message
below)"
echo
fi
sync
+exec /sbin/guestfs_poweroff
diff --git a/appliance/update.sh.in b/appliance/update.sh.in
index 0222a75..9cb3450 100755
--- a/appliance/update.sh.in
+++ b/appliance/update.sh.in
@@ -33,6 +33,10 @@ if [ "@DIST@" = "REDHAT" ]; then
# Copy the daemon into the filesystem.
@FEBOOTSTRAP_INSTALL@ initramfs daemon/guestfsd /sbin/guestfsd 0755 root.root
+ # Copy guestfs_poweroff into the filesystem
+ febootstrap-install initramfs appliance/guestfs_poweroff \
+ /sbin/guestfs_poweroff 0755 root.root
+
# Generate final image.
@FEBOOTSTRAP_TO_INITRAMFS@ initramfs > $output-t
mv $output-t $output
diff --git a/po/POTFILES.in b/po/POTFILES.in
index e5fb857..b2f7f26 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+appliance/guestfs_poweroff.c
daemon/augeas.c
daemon/available.c
daemon/base64.c
--
1.7.2.2
Matthew Booth
2010-Aug-26 11:12 UTC
[Libguestfs] [PATCH 4/4] Ignore launch() error in virt-rescue
launch() expects guestfsd to start, which it never does in virt-rescue, so it
always returns an error about the appliance shutting down unexpectedly.
---
tools/virt-rescue | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/tools/virt-rescue b/tools/virt-rescue
index 1f292f6..f466b43 100755
--- a/tools/virt-rescue
+++ b/tools/virt-rescue
@@ -214,7 +214,8 @@ $g->set_append ($str);
# Run the appliance. This won't return until the user quite the
# appliance.
-$g->launch ();
+# This will definitely return an error because we don't run the daemon
+eval { $g->launch (); };
exit 0;
--
1.7.2.2