From 48f8d8a95d6e963089e4daeeafe96e52b1f7bfc1 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Sat, 5 Mar 2011 10:44:50 -0500 Subject: [PATCH] Use block instead of scsi devices for LUNs Signed-off-by: David Zeuthen --- src/udiskslinuxlun.c | 41 ++++++++------- src/udiskslinuxprovider.c | 128 +++++++++++++++++++++++++--------------------- 2 files changed, 90 insertions(+), 79 deletions(-) diff --git a/src/udiskslinuxlun.c b/src/udiskslinuxlun.c index d39962b..db0cbe5 100644 --- a/src/udiskslinuxlun.c +++ b/src/udiskslinuxlun.c @@ -48,7 +48,7 @@ struct _UDisksLinuxLun UDisksDaemon *daemon; - /* list of GUdevDevice objects for scsi_device objects */ + /* list of GUdevDevice objects for block objects */ GList *devices; /* interfaces */ @@ -301,7 +301,7 @@ udisks_linux_lun_class_init (UDisksLinuxLunClass *klass) /** * udisks_linux_lun_new: * @daemon: A #UDisksDaemon. - * @device: The #GUdevDevice for the sysfs scsi device. + * @device: The #GUdevDevice for the sysfs block device. * * Create a new lun object. * @@ -493,13 +493,26 @@ lun_update (UDisksLinuxLun *lun, udisks_lun_set_serial (iface, g_udev_device_get_property (device, "ID_SCSI_SERIAL")); udisks_lun_set_wwn (iface, g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION")); } + else if (g_str_has_prefix (g_udev_device_get_name (device), "mmcblk")) + { + /* sigh, mmc is non-standard and using ID_NAME instead of ID_MODEL.. */ + udisks_lun_set_model (iface, g_udev_device_get_property (device, "ID_NAME")); + udisks_lun_set_serial (iface, g_udev_device_get_property (device, "ID_SERIAL")); + /* TODO: + * - lookup Vendor from manfid and oemid in sysfs + * - lookup Revision from fwrev and hwrev in sysfs + */ + } else { /* generic fallback... */ udisks_lun_set_vendor (iface, g_udev_device_get_property (device, "ID_VENDOR")); udisks_lun_set_model (iface, g_udev_device_get_property (device, "ID_MODEL")); udisks_lun_set_revision (iface, g_udev_device_get_property (device, "ID_REVISION")); - udisks_lun_set_serial (iface, g_udev_device_get_property (device, "ID_SERIAL_SHORT")); + if (g_udev_device_has_property (device, "ID_SERIAL_SHORT")) + udisks_lun_set_serial (iface, g_udev_device_get_property (device, "ID_SERIAL_SHORT")); + else + udisks_lun_set_serial (iface, g_udev_device_get_property (device, "ID_SERIAL")); udisks_lun_set_wwn (iface, g_udev_device_get_property (device, "ID_WWN_WITH_EXTENSION")); } @@ -596,35 +609,21 @@ udisks_linux_lun_should_include_device (GUdevDevice *device, gchar **out_vpd) { gboolean ret; - gint type; const gchar *serial; const gchar *wwn; const gchar *vpd; ret = FALSE; - /* The 'scsi' subsystem encompasses several objects with varying + /* The 'block' subsystem encompasses several objects with varying * DEVTYPE including * - * - scsi_device - * - scsi_target - * - scsi_host + * - disk + * - partition * * and we are only interested in the first. */ - if (g_strcmp0 (g_udev_device_get_devtype (device), "scsi_device") != 0) - goto out; - - /* In fact, we are only interested in SCSI devices with peripheral type - * 0x00 (Direct-access block device) and 0x05 (CD/DVD device). If we - * didn't do this check we'd end up adding Enclosure Services Devices - * and RAID controllers here. - * - * See SPC-4, section 6.4.2: Standard INQUIRY data for where - * the various peripheral types are defined. - */ - type = g_udev_device_get_sysfs_attr_as_int (device, "type"); - if (!(type == 0x00 || type == 0x05)) + if (g_strcmp0 (g_udev_device_get_devtype (device), "disk") != 0) goto out; /* prefer WWN to serial */ diff --git a/src/udiskslinuxprovider.c b/src/udiskslinuxprovider.c index c354a54..36b4401 100644 --- a/src/udiskslinuxprovider.c +++ b/src/udiskslinuxprovider.c @@ -109,7 +109,7 @@ static void udisks_linux_provider_constructed (GObject *object) { UDisksLinuxProvider *provider = UDISKS_LINUX_PROVIDER (object); - const gchar *subsystems[] = {"block", "scsi", NULL}; + const gchar *subsystems[] = {"block", NULL}; GList *devices; GList *l; @@ -137,12 +137,6 @@ udisks_linux_provider_constructed (GObject *object) g_free, (GDestroyNotify) g_object_unref); - devices = g_udev_client_query_by_subsystem (provider->gudev_client, "scsi"); - for (l = devices; l != NULL; l = l->next) - udisks_linux_provider_handle_uevent (provider, "add", G_UDEV_DEVICE (l->data)); - g_list_foreach (devices, (GFunc) g_object_unref, NULL); - g_list_free (devices); - devices = g_udev_client_query_by_subsystem (provider->gudev_client, "block"); for (l = devices; l != NULL; l = l->next) udisks_linux_provider_handle_uevent (provider, "add", G_UDEV_DEVICE (l->data)); @@ -187,7 +181,7 @@ udisks_linux_provider_new (UDisksDaemon *daemon) * * Gets the #GUdevClient used by @provider. The returned object is set * up so it emits #GUdevClient::uevent signals only for the - * block and scsi subsystems. + * block. * * Returns: A #GUdevClient owned by @provider. Do not free. */ @@ -201,51 +195,9 @@ udisks_linux_provider_get_udev_client (UDisksLinuxProvider *provider) /* ---------------------------------------------------------------------------------------------------- */ static void -handle_block_uevent (UDisksLinuxProvider *provider, - const gchar *action, - GUdevDevice *device) -{ - const gchar *sysfs_path; - UDisksLinuxBlock *block; - UDisksDaemon *daemon; - - daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider)); - sysfs_path = g_udev_device_get_sysfs_path (device); - - if (g_strcmp0 (action, "remove") == 0) - { - block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); - if (block != NULL) - { - gchar *object_path; - object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (block)); - g_dbus_object_manager_unexport (udisks_daemon_get_object_manager (daemon), - object_path); - g_free (object_path); - g_warn_if_fail (g_hash_table_remove (provider->sysfs_to_block, sysfs_path)); - } - } - else - { - block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); - if (block != NULL) - { - udisks_linux_block_uevent (block, action, device); - } - else - { - block = udisks_linux_block_new (daemon, device); - g_dbus_object_manager_export_and_uniquify (udisks_daemon_get_object_manager (daemon), - G_DBUS_OBJECT (block)); - g_hash_table_insert (provider->sysfs_to_block, g_strdup (sysfs_path), block); - } - } -} - -static void -handle_scsi_uevent (UDisksLinuxProvider *provider, - const gchar *action, - GUdevDevice *device) +handle_block_uevent_for_lun (UDisksLinuxProvider *provider, + const gchar *action, + GUdevDevice *device) { UDisksLinuxLun *lun; UDisksDaemon *daemon; @@ -294,7 +246,7 @@ handle_scsi_uevent (UDisksLinuxProvider *provider, { udisks_daemon_log (daemon, UDISKS_LOG_LEVEL_WARNING, - "Ignoring scsi_device %s with no serial or WWN", + "Ignoring block %s with no serial or WWN", g_udev_device_get_sysfs_path (device)); goto out; } @@ -324,6 +276,70 @@ handle_scsi_uevent (UDisksLinuxProvider *provider, } static void +handle_block_uevent_for_block (UDisksLinuxProvider *provider, + const gchar *action, + GUdevDevice *device) +{ + const gchar *sysfs_path; + UDisksLinuxBlock *block; + UDisksDaemon *daemon; + + daemon = udisks_provider_get_daemon (UDISKS_PROVIDER (provider)); + sysfs_path = g_udev_device_get_sysfs_path (device); + + if (g_strcmp0 (action, "remove") == 0) + { + block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); + if (block != NULL) + { + gchar *object_path; + object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (block)); + g_dbus_object_manager_unexport (udisks_daemon_get_object_manager (daemon), + object_path); + g_free (object_path); + g_warn_if_fail (g_hash_table_remove (provider->sysfs_to_block, sysfs_path)); + } + } + else + { + block = g_hash_table_lookup (provider->sysfs_to_block, sysfs_path); + if (block != NULL) + { + udisks_linux_block_uevent (block, action, device); + } + else + { + block = udisks_linux_block_new (daemon, device); + g_dbus_object_manager_export_and_uniquify (udisks_daemon_get_object_manager (daemon), + G_DBUS_OBJECT (block)); + g_hash_table_insert (provider->sysfs_to_block, g_strdup (sysfs_path), block); + } + } +} + + +static void +handle_block_uevent (UDisksLinuxProvider *provider, + const gchar *action, + GUdevDevice *device) +{ + /* We use the sysfs block device for both LUNs and BlockDevice + * objects. Ensure that LUNs are added before and removed after + * BlockDevice + */ + if (g_strcmp0 (action, "remove") == 0) + { + handle_block_uevent_for_block (provider, action, device); + handle_block_uevent_for_lun (provider, action, device); + } + else + { + handle_block_uevent_for_lun (provider, action, device); + handle_block_uevent_for_block (provider, action, device); + } +} + +static void udisks_linux_provider_handle_uevent (UDisksLinuxProvider *provider, const gchar *action, GUdevDevice *device) @@ -344,8 +360,4 @@ udisks_linux_provider_handle_uevent (UDisksLinuxProvider *provider, { handle_block_uevent (provider, action, device); } - else if (g_strcmp0 (subsystem, "scsi") == 0) - { - handle_scsi_uevent (provider, action, device); - } } -- 2.7.4