diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-06-29 16:45:07 +0100 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-07-06 17:36:29 +0100 |
commit | 9e38de7449cd746cca326b0f60091e0eb99bb89d (patch) | |
tree | 928c5c142b0dcc5e55c5e919bf7b6c1f1cbaf43a | |
parent | 3fe9235b90ec128cd59407100a1b49c7d4a581de (diff) | |
download | libguestfs-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.c | 74 |
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) */ |