summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-06-29 16:45:07 +0100
committerRichard W.M. Jones <rjones@redhat.com>2012-07-06 17:36:29 +0100
commit9e38de7449cd746cca326b0f60091e0eb99bb89d (patch)
tree928c5c142b0dcc5e55c5e919bf7b6c1f1cbaf43a
parent3fe9235b90ec128cd59407100a1b49c7d4a581de (diff)
downloadlibguestfs-9e38de7449cd746cca326b0f60091e0eb99bb89d.tar.gz
libguestfs-9e38de7449cd746cca326b0f60091e0eb99bb89d.tar.xz
libguestfs-9e38de7449cd746cca326b0f60091e0eb99bb89d.zip
inspect: Guess device name from /dev/disk/by-id/*-partN path (RHBZ#627675).
See https://bugzilla.redhat.com/show_bug.cgi?id=836573#c3 for an explanation. Useful function 'is_partition' shows how to tell if a device name represents a partition. (cherry picked from commit 7eaa99994ebd354f4b078d4068695984989a907f)
-rw-r--r--src/inspect_fs_unix.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/inspect_fs_unix.c b/src/inspect_fs_unix.c
index 6eb3809c..94e912c0 100644
--- a/src/inspect_fs_unix.c
+++ b/src/inspect_fs_unix.c
@@ -68,6 +68,7 @@ static pcre *re_xdev;
static pcre *re_cciss;
static pcre *re_mdN;
static pcre *re_freebsd;
+static pcre *re_diskbyid;
static pcre *re_netbsd;
static void compile_regexps (void) __attribute__((constructor));
@@ -112,6 +113,7 @@ compile_regexps (void)
COMPILE (re_cciss, "^/dev/(cciss/c\\d+d\\d+)(?:p(\\d+))?$", 0);
COMPILE (re_mdN, "^(/dev/md\\d+)$", 0);
COMPILE (re_freebsd, "^/dev/ad(\\d+)s(\\d+)([a-z])$", 0);
+ COMPILE (re_diskbyid, "^/dev/disk/by-id/.*-part(\\d+)$", 0);
COMPILE (re_netbsd, "^NetBSD (\\d+)\\.(\\d+)", 0);
}
@@ -133,6 +135,7 @@ free_regexps (void)
pcre_free (re_cciss);
pcre_free (re_mdN);
pcre_free (re_freebsd);
+ pcre_free (re_diskbyid);
pcre_free (re_netbsd);
}
@@ -147,6 +150,7 @@ static int add_fstab_entry (guestfs_h *g, struct inspect_fs *fs,
static char *resolve_fstab_device (guestfs_h *g, const char *spec,
Hash_table *md_map);
static int inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs, const char **configfiles, int (*f) (guestfs_h *, struct inspect_fs *));
+static int is_partition (guestfs_h *g, const char *partition);
/* Hash structure for uuid->path lookups */
typedef struct md_uuid {
@@ -1281,6 +1285,44 @@ resolve_fstab_device_cciss (guestfs_h *g, const char *disk, const char *part,
return 0;
}
+static int
+resolve_fstab_device_diskbyid (guestfs_h *g, const char *part,
+ char **device_ret)
+{
+ int nr_devices;
+ char *device;
+
+ /* For /dev/disk/by-id there is a limit to what we can do because
+ * original SCSI ID information has likely been lost. This
+ * heuristic will only work for guests that have a single block
+ * device.
+ *
+ * So the main task here is to make sure the assumptions above are
+ * true.
+ *
+ * XXX Use hints from virt-p2v if available.
+ * See also: https://bugzilla.redhat.com/show_bug.cgi?id=836573#c3
+ */
+
+ nr_devices = guestfs_nr_devices (g);
+ if (nr_devices == -1)
+ return -1;
+
+ /* If #devices isn't 1, give up trying to translate this fstab entry. */
+ if (nr_devices != 1)
+ return 0;
+
+ /* Make the partition name and check it exists. */
+ device = safe_asprintf (g, "/dev/sda%s", part);
+ if (!is_partition (g, device)) {
+ free (device);
+ return 0;
+ }
+
+ *device_ret = device;
+ return 0;
+}
+
/* Resolve block device name to the libguestfs device name, eg.
* /dev/xvdb1 => /dev/vdb1; and /dev/mapper/VG-LV => /dev/VG/LV. This
* assumes that disks were added in the same order as they appear to
@@ -1351,6 +1393,12 @@ resolve_fstab_device (guestfs_h *g, const char *spec, Hash_table *md_map)
device = safe_asprintf (g, "/dev/sd%c%d", disk_i + 'a', part_i + 5);
}
}
+ else if ((part = match1 (g, spec, re_diskbyid)) != NULL) {
+ r = resolve_fstab_device_diskbyid (g, part, &device);
+ free (part);
+ if (r == -1)
+ return NULL;
+ }
/* Didn't match device pattern, return original spec unchanged. */
if (device == NULL)
@@ -1442,4 +1490,30 @@ inspect_with_augeas (guestfs_h *g, struct inspect_fs *fs,
return r;
}
+static int
+is_partition (guestfs_h *g, const char *partition)
+{
+ char *device;
+ guestfs_error_handler_cb old_error_cb;
+
+ old_error_cb = g->error_cb;
+ g->error_cb = NULL;
+
+ if ((device = guestfs_part_to_dev (g, partition)) == NULL) {
+ g->error_cb = old_error_cb;
+ return 0;
+ }
+
+ if (guestfs_device_index (g, device) == -1) {
+ g->error_cb = old_error_cb;
+ free (device);
+ return 0;
+ }
+
+ g->error_cb = old_error_cb;
+ free (device);
+
+ return 1;
+}
+
#endif /* defined(HAVE_HIVEX) */