[Libguestfs] [PATCH] Fix: virt-inspector takes ages to run on RHEL 3 guests
Richard W.M. Jones
rjones at redhat.com
Mon Jul 13 17:23:45 UTC 2009
Currently virt-inspector takes ages to run on RHEL 3 guests.
I tracked this down to processing the old-style initrd images in these
guests. These initrd images are compressed ext2 filesystems. 'cpio'
tries to parse them as cpio files, and takes a very long time to fail
(and spews out a lot of errors in the process).
These two patches fix the problem: Firstly we introduce a new command
'zfile' for doing the 'file' operation inside compressed files. eg:
guestfs_zfile (g, "gzip", "/boot/initrd.img")
==> "Linux rev 1.0 ext2 filesystem data"
Second patch updates Sys::Guestfs::Lib to ignore such files.
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-df lists disk usage of guests without needing to install any
software inside the virtual machine. Supports Linux and Windows.
http://et.redhat.com/~rjones/virt-df/
-------------- next part --------------
>From 7d41d75c1d4e6dbe61f6cd353bc104663340483f Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at trick.home.annexia.org>
Date: Mon, 13 Jul 2009 18:00:07 +0100
Subject: [PATCH 1/2] Implement new 'zfile' command, to show file type inside compressed files.
---
daemon/file.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/MAX_PROC_NR | 2 +-
src/generator.ml | 51 +++++++++++++++++++++++++++------------------
3 files changed, 92 insertions(+), 21 deletions(-)
diff --git a/daemon/file.c b/daemon/file.c
index 3ef7441..98c356d 100644
--- a/daemon/file.c
+++ b/daemon/file.c
@@ -376,3 +376,63 @@ do_file (char *path)
return out; /* caller frees */
}
+
+/* zcat | file */
+char *
+do_zfile (char *method, char *path)
+{
+ int len;
+ char *cmd;
+ FILE *fp;
+ char line[256];
+
+ NEED_ROOT (NULL);
+ ABS_PATH (path, NULL);
+
+ len = 2 * strlen (path) + 64;
+ cmd = malloc (len);
+ if (!cmd) {
+ reply_with_perror ("malloc");
+ return NULL;
+ }
+
+ if (strcmp (method, "gzip") == 0 || strcmp (method, "compress") == 0)
+ strcpy (cmd, "zcat");
+ else if (strcmp (method, "bzip2") == 0)
+ strcpy (cmd, "bzcat");
+ else {
+ free (cmd);
+ reply_with_error ("zfile: unknown method");
+ return NULL;
+ }
+
+ strcat (cmd, " /sysroot");
+ shell_quote (cmd + strlen (cmd), len - strlen (cmd), path);
+ strcat (cmd, " | file -bsL -");
+
+ fp = popen (cmd, "r");
+ if (fp == NULL) {
+ reply_with_perror ("%s", cmd);
+ free (cmd);
+ return NULL;
+ }
+
+ free (cmd);
+
+ if (fgets (line, sizeof line, fp) == NULL) {
+ reply_with_perror ("zfile: fgets");
+ fclose (fp);
+ return NULL;
+ }
+
+ if (fclose (fp) == -1) {
+ reply_with_perror ("zfile: fclose");
+ return NULL;
+ }
+
+ len = strlen (line);
+ if (len > 0 && line[len-1] == '\n')
+ line[len-1] = '\0';
+
+ return strdup (line);
+}
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index 897bdc8..dee261d 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-139
+140
diff --git a/src/generator.ml b/src/generator.ml
index 8c864f0..e3293d1 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -1718,8 +1718,8 @@ This uses the L<blockdev(8)> command.");
("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
[InitBasicFS, Always, TestOutput (
(* Pick a file from cwd which isn't likely to change. *)
- [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
- ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
+ [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
+ ["checksum"; "md5"; "/COPYING.LIB"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
"upload a file from the local machine",
"\
Upload local file C<filename> to C<remotefilename> on the
@@ -1732,10 +1732,10 @@ See also C<guestfs_download>.");
("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
[InitBasicFS, Always, TestOutput (
(* Pick a file from cwd which isn't likely to change. *)
- [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
- ["download"; "/COPYING.LIB"; "testdownload.tmp"];
- ["upload"; "testdownload.tmp"; "/upload"];
- ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
+ [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
+ ["download"; "/COPYING.LIB"; "testdownload.tmp"];
+ ["upload"; "testdownload.tmp"; "/upload"];
+ ["checksum"; "md5"; "/upload"]], "e3eda01d9815f8d24aae2dbd89b68b06")],
"download a file to the local machine",
"\
Download file C<remotefilename> and save it as C<filename>
@@ -2357,19 +2357,19 @@ are activated or deactivated.");
("lvresize", (RErr, [String "device"; Int "mbytes"]), 105, [],
[InitNone, Always, TestOutput (
- [["sfdiskM"; "/dev/sda"; ","];
- ["pvcreate"; "/dev/sda1"];
- ["vgcreate"; "VG"; "/dev/sda1"];
- ["lvcreate"; "LV"; "VG"; "10"];
- ["mkfs"; "ext2"; "/dev/VG/LV"];
- ["mount"; "/dev/VG/LV"; "/"];
- ["write_file"; "/new"; "test content"; "0"];
- ["umount"; "/"];
- ["lvresize"; "/dev/VG/LV"; "20"];
- ["e2fsck_f"; "/dev/VG/LV"];
- ["resize2fs"; "/dev/VG/LV"];
- ["mount"; "/dev/VG/LV"; "/"];
- ["cat"; "/new"]], "test content")],
+ [["sfdiskM"; "/dev/sda"; ","];
+ ["pvcreate"; "/dev/sda1"];
+ ["vgcreate"; "VG"; "/dev/sda1"];
+ ["lvcreate"; "LV"; "VG"; "10"];
+ ["mkfs"; "ext2"; "/dev/VG/LV"];
+ ["mount"; "/dev/VG/LV"; "/"];
+ ["write_file"; "/new"; "test content"; "0"];
+ ["umount"; "/"];
+ ["lvresize"; "/dev/VG/LV"; "20"];
+ ["e2fsck_f"; "/dev/VG/LV"];
+ ["resize2fs"; "/dev/VG/LV"];
+ ["mount"; "/dev/VG/LV"; "/"];
+ ["cat"; "/new"]], "test content")],
"resize an LVM logical volume",
"\
This resizes (expands or shrinks) an existing LVM logical
@@ -2441,7 +2441,7 @@ This command is only needed because of C<guestfs_resize2fs>
("sleep", (RErr, [Int "secs"]), 109, [],
[InitNone, Always, TestRun (
- [["sleep"; "1"]])],
+ [["sleep"; "1"]])],
"sleep for some seconds",
"\
Sleep for C<secs> seconds.");
@@ -2857,6 +2857,17 @@ were rarely if ever used anyway.
See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
+ ("zfile", (RString "description", [String "method"; String "path"]), 140, [],
+ [],
+ "determine file type inside a compressed file",
+ "\
+This command runs C<file> after first decompressing C<path>
+using C<method>.
+
+C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
+
+See also: C<guestfs_file>");
+
]
let all_functions = non_daemon_functions @ daemon_functions
--
1.6.2.5
-------------- next part --------------
>From 4e444d5c09d78b0d292d95d1f97de12f26cc139d Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones at trick.home.annexia.org>
Date: Mon, 13 Jul 2009 18:06:10 +0100
Subject: [PATCH 2/2] Ignore old-style initrd which is a compressed ext2 filesystem.
'cpio' chokes on these, taking ages to decide that they are
not cpio files, and producing masses of messages. This was
causing virt-inspector to be very slow (many minutes) on
RHEL 3 guests. With this fix, speed is back to normal.
---
perl/lib/Sys/Guestfs/Lib.pm | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/perl/lib/Sys/Guestfs/Lib.pm b/perl/lib/Sys/Guestfs/Lib.pm
index 27a7b9e..d5dfb4e 100644
--- a/perl/lib/Sys/Guestfs/Lib.pm
+++ b/perl/lib/Sys/Guestfs/Lib.pm
@@ -1208,14 +1208,20 @@ sub _check_for_initrd
my $version = $1;
my @modules;
- eval {
- @modules = $g->initrd_list ("/boot/$initrd");
- };
- unless ($@) {
- @modules = grep { m,([^/]+)\.ko$, || m,([^/]+)\.o$, } @modules;
- $initrd_modules{$version} = \@modules
- } else {
- warn "/boot/$initrd: could not read initrd format"
+ # Disregard old-style compressed ext2 files, since cpio
+ # takes ages to (fail to) process these.
+ if ($g->file ("/boot/$initrd") !~ /gzip compressed/ ||
+ $g->zfile ("gzip", "/boot/$initrd") !~ /ext2 filesystem/) {
+ eval {
+ @modules = $g->initrd_list ("/boot/$initrd");
+ };
+ unless ($@) {
+ @modules = grep { m,([^/]+)\.ko$, || m,([^/]+)\.o$, }
+ @modules;
+ $initrd_modules{$version} = \@modules
+ } else {
+ warn "/boot/$initrd: could not read initrd format";
+ }
}
}
}
--
1.6.2.5
More information about the Libguestfs
mailing list