diff options
author | David Zeuthen <davidz@redhat.com> | 2011-08-13 12:02:39 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2011-08-13 12:02:39 -0400 |
commit | fa2c478a89ec454a3594bf6fbc5368130819bd38 (patch) | |
tree | a9e01460d6f1a05a906032f89614a1539505cead | |
parent | 609fcd3515942140c14561e516923af70a6d4128 (diff) |
Associate dm-multipath devices with the correct drive
http://people.freedesktop.org/~david/palimpsest-multipath.png
Signed-off-by: David Zeuthen <davidz@redhat.com>
-rw-r--r-- | src/udiskslinuxdrive.c | 91 | ||||
-rw-r--r-- | src/udiskslinuxdrive.h | 3 | ||||
-rw-r--r-- | src/udiskslinuxprovider.c | 2 |
3 files changed, 74 insertions, 22 deletions
diff --git a/src/udiskslinuxdrive.c b/src/udiskslinuxdrive.c index 471ef28..408828e 100644 --- a/src/udiskslinuxdrive.c +++ b/src/udiskslinuxdrive.c @@ -175,16 +175,24 @@ udisks_linux_drive_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) { - GObjectConstructParam *device_cp; + GObjectConstructParam *cp; + UDisksDaemon *daemon; + GUdevClient *client; GUdevDevice *device; - device_cp = find_construct_property (n_construct_properties, construct_properties, "device"); - g_assert (device_cp != NULL); + cp = find_construct_property (n_construct_properties, construct_properties, "daemon"); + g_assert (cp != NULL); + daemon = UDISKS_DAEMON (g_value_get_object (cp->value)); + g_assert (daemon != NULL); + + client = udisks_linux_provider_get_udev_client (udisks_daemon_get_linux_provider (daemon)); - device = G_UDEV_DEVICE (g_value_get_object (device_cp->value)); + cp = find_construct_property (n_construct_properties, construct_properties, "device"); + g_assert (cp != NULL); + device = G_UDEV_DEVICE (g_value_get_object (cp->value)); g_assert (device != NULL); - if (!udisks_linux_drive_should_include_device (device, NULL)) + if (!udisks_linux_drive_should_include_device (client, device, NULL)) { return NULL; } @@ -1242,8 +1250,34 @@ udisks_linux_drive_uevent (UDisksLinuxDrive *drive, /* ---------------------------------------------------------------------------------------------------- */ +static gchar * +check_for_vpd (GUdevDevice *device) +{ + gchar *ret; + const gchar *serial; + const gchar *wwn; + + g_return_val_if_fail (G_UDEV_IS_DEVICE (device), FALSE); + + ret = NULL; + + /* prefer WWN to serial */ + serial = g_udev_device_get_property (device, "ID_SERIAL"); + wwn = g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION"); + if (wwn != NULL && strlen (wwn) > 0) + { + ret = g_strdup (wwn); + } + else if (serial != NULL && strlen (serial) > 0) + { + ret = g_strdup (serial); + } + return ret; +} + /* <internal> * udisks_linux_drive_should_include_device: + * @client: A #GUdevClient. * @device: A #GUdevDevice. * @out_vpd: Return location for unique ID or %NULL. * @@ -1252,12 +1286,11 @@ udisks_linux_drive_uevent (UDisksLinuxDrive *drive, * Returns: %TRUE if we should construct an object, %FALSE otherwise. */ gboolean -udisks_linux_drive_should_include_device (GUdevDevice *device, +udisks_linux_drive_should_include_device (GUdevClient *client, + GUdevDevice *device, gchar **out_vpd) { gboolean ret; - const gchar *serial; - const gchar *wwn; gchar *vpd; ret = FALSE; @@ -1274,18 +1307,9 @@ udisks_linux_drive_should_include_device (GUdevDevice *device, if (g_strcmp0 (g_udev_device_get_devtype (device), "disk") != 0) goto out; - /* prefer WWN to serial */ - serial = g_udev_device_get_property (device, "ID_SERIAL"); - wwn = g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION"); - if (wwn != NULL && strlen (wwn) > 0) - { - vpd = g_strdup (wwn); - } - else if (serial != NULL && strlen (serial) > 0) - { - vpd = g_strdup (serial); - } - else + vpd = check_for_vpd (device); + + if (vpd == NULL) { const gchar *name; GUdevDevice *parent; @@ -1307,6 +1331,33 @@ udisks_linux_drive_should_include_device (GUdevDevice *device, g_object_unref (parent); goto found; } + + /* dm-multipath */ + const gchar *dm_name; + dm_name = g_udev_device_get_sysfs_attr (device, "dm/name"); + if (dm_name != NULL && g_str_has_prefix (dm_name, "mpath")) + { + gchar **slaves; + guint n; + slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device), "slaves"); + for (n = 0; slaves[n] != NULL; n++) + { + GUdevDevice *slave; + slave = g_udev_client_query_by_sysfs_path (client, slaves[n]); + if (slave != NULL) + { + vpd = check_for_vpd (slave); + if (vpd != NULL) + { + g_object_unref (slave); + g_strfreev (slaves); + goto found; + } + g_object_unref (slave); + } + } + g_strfreev (slaves); + } } found: diff --git a/src/udiskslinuxdrive.h b/src/udiskslinuxdrive.h index f4a1593..e287ebb 100644 --- a/src/udiskslinuxdrive.h +++ b/src/udiskslinuxdrive.h @@ -44,7 +44,8 @@ gboolean udisks_linux_drive_housekeeping (UDisksLinuxDrive *drive, GCancellable *cancellable, GError **error); -gboolean udisks_linux_drive_should_include_device (GUdevDevice *device, +gboolean udisks_linux_drive_should_include_device (GUdevClient *client, + GUdevDevice *device, gchar **out_vpd); G_END_DECLS diff --git a/src/udiskslinuxprovider.c b/src/udiskslinuxprovider.c index 60da384..39d599d 100644 --- a/src/udiskslinuxprovider.c +++ b/src/udiskslinuxprovider.c @@ -344,7 +344,7 @@ handle_block_uevent_for_drive (UDisksLinuxProvider *provider, } else { - if (!udisks_linux_drive_should_include_device (device, &vpd)) + if (!udisks_linux_drive_should_include_device (provider->gudev_client, device, &vpd)) goto out; if (vpd == NULL) |