Nikos Skalkotos
2014-Nov-27 16:30 UTC
[Libguestfs] [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
The assumption that Linux will map the MBR partition to /dev/sda1
and the BSD 'a' partition to /dev/sda5 is not always correct.
Signed-off-by: Nikos Skalkotos <skalkoto@grnet.gr>
---
src/guestfs-internal.h | 1 +
src/inspect-fs.c | 55 +++++++++++++++++++++++++++++++++-----------------
src/inspect.c | 6 ++++++
3 files changed, 43 insertions(+), 19 deletions(-)
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index fd0c4a1..2460d25 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -746,6 +746,7 @@ extern int guestfs___is_file_nocase (guestfs_h *g, const
char *);
extern int guestfs___is_dir_nocase (guestfs_h *g, const char *);
extern int guestfs___check_for_filesystem_on (guestfs_h *g,
const char *mountable);
+extern void guestfs___check_for_dublicated_bsd_root(guestfs_h *g);
extern int guestfs___parse_unsigned_int (guestfs_h *g, const char *str);
extern int guestfs___parse_unsigned_int_ignore_trailing (guestfs_h *g, const
char *str);
extern int guestfs___parse_major_minor (guestfs_h *g, struct inspect_fs *fs);
diff --git a/src/inspect-fs.c b/src/inspect-fs.c
index 539d814..99a8658 100644
--- a/src/inspect-fs.c
+++ b/src/inspect-fs.c
@@ -47,7 +47,7 @@
* multiple threads call into the libguestfs API functions below
* simultaneously.
*/
-static pcre *re_first_partition;
+static pcre *re_primary_partition;
static pcre *re_major_minor;
static void compile_regexps (void) __attribute__((constructor));
@@ -68,14 +68,14 @@ compile_regexps (void)
} \
} while (0)
- COMPILE (re_first_partition, "^/dev/(?:h|s|v)d.1$", 0);
+ COMPILE (re_primary_partition, "^/dev/(?:h|s|v)d.[1234]$", 0);
COMPILE (re_major_minor, "(\\d+)\\.(\\d+)", 0);
}
static void
free_regexps (void)
{
- pcre_free (re_first_partition);
+ pcre_free (re_primary_partition);
pcre_free (re_major_minor);
}
@@ -84,6 +84,39 @@ static int check_filesystem (guestfs_h *g, const char
*mountable,
int whole_device);
static int extend_fses (guestfs_h *g);
+/* On *BSD systems, sometimes /dev/sda[1234] is a shadow of the real root
+ * filesystem that is probably /dev/sda5
+ * (see: http://www.freebsd.org/doc/handbook/disk-organization.html)
+ */
+void
+guestfs___check_for_dublicated_bsd_root(guestfs_h *g)
+{
+ size_t i;
+ bool is_primary, is_bsd;
+ struct inspect_fs *fs, *bsd_primary = NULL;
+
+ for (i = 0; i < g->nr_fses; ++i) {
+ fs = &g->fses[i];
+
+ is_primary = match (g, fs->mountable, re_primary_partition);
+ is_bsd = ((fs->type == OS_TYPE_FREEBSD) || \
+ (fs->type == OS_TYPE_NETBSD) || \
+ (fs->type == OS_TYPE_OPENBSD));
+
+ if (fs->is_root && is_primary && is_bsd) {
+ bsd_primary = fs;
+ continue;
+ }
+
+ if (fs->is_root && bsd_primary && (bsd_primary->type
== fs->type)) {
+ /* remove the is root flag from the bsd_primary */
+ bsd_primary->is_root = 0;
+ bsd_primary->format = OS_FORMAT_UNKNOWN;
+ return;
+ }
+ }
+}
+
/* Find out if 'device' contains a filesystem. If it does, add
* another entry in g->fses.
*/
@@ -207,14 +240,6 @@ check_filesystem (guestfs_h *g, const char *mountable,
is_dir_bin &&
guestfs_is_file (g, "/etc/freebsd-update.conf") > 0
&&
guestfs_is_file (g, "/etc/fstab") > 0) {
- /* Ignore /dev/sda1 which is a shadow of the real root filesystem
- * that is probably /dev/sda5 (see:
- * http://www.freebsd.org/doc/handbook/disk-organization.html)
- */
- if (m->im_type == MOUNTABLE_DEVICE &&
- match (g, m->im_device, re_first_partition))
- return 0;
-
fs->is_root = 1;
fs->format = OS_FORMAT_INSTALLED;
if (guestfs___check_freebsd_root (g, fs) == -1)
@@ -225,14 +250,6 @@ check_filesystem (guestfs_h *g, const char *mountable,
guestfs_is_file (g, "/netbsd") > 0 &&
guestfs_is_file (g, "/etc/fstab") > 0 &&
guestfs_is_file (g, "/etc/release") > 0) {
- /* Ignore /dev/sda1 which is a shadow of the real root filesystem
- * that is probably /dev/sda5 (see:
- * http://www.freebsd.org/doc/handbook/disk-organization.html)
- */
- if (m->im_type == MOUNTABLE_DEVICE &&
- match (g, m->im_device, re_first_partition))
- return 0;
-
fs->is_root = 1;
fs->format = OS_FORMAT_INSTALLED;
if (guestfs___check_netbsd_root (g, fs) == -1)
diff --git a/src/inspect.c b/src/inspect.c
index 9248b06..048b059 100644
--- a/src/inspect.c
+++ b/src/inspect.c
@@ -64,6 +64,12 @@ guestfs__inspect_os (guestfs_h *g)
}
}
+ /* Check if the same filesystem was listed twice as root in g->fses.
+ * This may happen for the *BSD root partition where an MBR partition
+ * is a shadow of the real root partition probably /dev/sda5
+ */
+ guestfs___check_for_dublicated_bsd_root(g);
+
/* At this point we have, in the handle, a list of all filesystems
* found and data about each one. Now we assemble the list of
* filesystems which are root devices and return that to the user.
--
2.1.3
Richard W.M. Jones
2014-Nov-28 14:31 UTC
Re: [Libguestfs] [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
How about the attached patch? It's basically the same as your patch but I moved the code between files and tidied up some whitespace issues. Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com virt-builder quickly builds VMs from scratch http://libguestfs.org/virt-builder.1.html
Pino Toscano
2014-Nov-28 14:42 UTC
Re: [Libguestfs] [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
On Friday 28 November 2014 14:31:01 Richard W.M. Jones wrote:> How about the attached patch? It's basically the same as your patch > but I moved the code between files and tidied up some whitespace > issues.Present in both the patches:> +/* On *BSD systems, sometimes /dev/sda[1234] is a shadow of the real root > + * filesystem that is probably /dev/sda5 > + * (see: http://www.freebsd.org/doc/handbook/disk-organization.html) > + */ > +static void > +check_for_duplicated_bsd_root (guestfs_h *g) > +{ > + size_t i; > + bool is_primary, is_bsd; > + struct inspect_fs *fs, *bsd_primary = NULL; > + > + for (i = 0; i < g->nr_fses; ++i) { > + fs = &g->fses[i]; > + > + is_primary = match (g, fs->mountable, re_primary_partition); > + is_bsd > + fs->type == OS_TYPE_FREEBSD || > + fs->type == OS_TYPE_NETBSD || > + fs->type == OS_TYPE_OPENBSD; > + > + if (fs->is_root && is_primary && is_bsd) { > + bsd_primary = fs; > + continue; > + }This will run the regexp matching for every filesystem found; what about inlining the match call as last part of the if, like: is_bsd fs->type == OS_TYPE_FREEBSD || fs->type == OS_TYPE_NETBSD || fs->type == OS_TYPE_OPENBSD; if (fs->is_root && is_bsd && is_primary && match (g, fs->mountable, re_primary_partition)) { bsd_primary = fs; continue; } This way it is done only for *BSD filesystems, and is_primary is used only in that if anyway. Also, is_bsd and fs could be declared just inside the for, as they are not needed outside of it. -- Pino Toscano
Maybe Matching Threads
- [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
- Re: [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
- Re: [synnefo-devel] Re: [PATCH 1/1] inspect: Fix a bug in the *BSD root detection
- [PATCH 0/5] Improve inspection of /usr filesystems
- [PATCH REPOST 1/2] common/mlstdutils: Add return statement.