Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] udiskslinuxdevice: Fix dm-multipath ATA drives handling #1064

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions src/udiskslinuxdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ static gboolean probe_ata (UDisksLinuxDevice *device,
/**
* udisks_linux_device_new_sync:
* @udev_device: A #GUdevDevice.
* @udev_client: A #GUdevClient.
*
* Creates a new #UDisksLinuxDevice from @udev_device which includes
* probing the device for more information, if applicable.
Expand All @@ -109,7 +110,7 @@ static gboolean probe_ata (UDisksLinuxDevice *device,
* Returns: A #UDisksLinuxDevice.
*/
UDisksLinuxDevice *
udisks_linux_device_new_sync (GUdevDevice *udev_device)
udisks_linux_device_new_sync (GUdevDevice *udev_device, GUdevClient *udev_client)
{
UDisksLinuxDevice *device;
GError *error = NULL;
Expand All @@ -122,7 +123,7 @@ udisks_linux_device_new_sync (GUdevDevice *udev_device)
/* No point in probing on remove events */
if (!(g_strcmp0 (g_udev_device_get_action (udev_device), "remove") == 0))
{
if (!udisks_linux_device_reprobe_sync (device, NULL, &error))
if (!udisks_linux_device_reprobe_sync (device, udev_client, NULL, &error))
goto out;
}

Expand All @@ -142,29 +143,41 @@ udisks_linux_device_new_sync (GUdevDevice *udev_device)
/**
* udisks_linux_device_reprobe_sync:
* @device: A #UDisksLinuxDevice.
* @udev_client: A #GUdevClient.
* @cancellable: (allow-none): A #GCancellable or %NULL.
* @error: Return location for error or %NULL.
*
* Forcibly reprobe information on @device. The calling thread may be
* blocked for a non-trivial amount of time while the probing is
* underway.
*
* Probing is dm-multipath aware in which case an active path
* is looked up and udev attributes are fetched from there.
*
* Returns: %TRUE if reprobing succeeded, %FALSE otherwise.
*/
gboolean
udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,
GUdevClient *udev_client,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
const gchar *device_file;
gboolean is_mpath_path_device;
gboolean is_mpath_master;

/* FIXME: are these the correct keys? */
is_mpath_path_device = g_udev_device_get_property_as_int (device->udev_device, "DM_MULTIPATH_DEVICE_PATH") == 1;
is_mpath_master = g_udev_device_get_property_as_int (device->udev_device, "MPATH_DEVICE_READY") == 1;

device_file = g_udev_device_get_device_file (device->udev_device);

/* Get IDENTIFY DEVICE / IDENTIFY PACKET DEVICE data for ATA devices */
if (g_strcmp0 (g_udev_device_get_subsystem (device->udev_device), "block") == 0 &&
g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") == 0 &&
g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA"))
g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA") &&
!is_mpath_path_device)
{
if (!probe_ata (device, cancellable, error))
goto out;
Expand Down Expand Up @@ -215,6 +228,34 @@ udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,
if (!device->nvme_ns_info)
goto out;
}
else
/* Probe the dm-multipath devices */
if (g_strcmp0 (g_udev_device_get_subsystem (device->udev_device), "block") == 0 &&
g_strcmp0 (g_udev_device_get_devtype (device->udev_device), "disk") == 0 &&
is_mpath_master)
{
gboolean is_ata = FALSE;
gchar **slaves;
guint n;

slaves = udisks_daemon_util_resolve_links (g_udev_device_get_sysfs_path (device->udev_device), "slaves");
for (n = 0; slaves[n] != NULL; n++)
{
GUdevDevice *slave;

slave = g_udev_client_query_by_sysfs_path (udev_client, slaves[n]);
if (slave != NULL)
{
is_ata |= g_udev_device_get_property_as_boolean (slave, "ID_ATA");
g_object_unref (slave);
}
if (is_ata)
break;
}
g_strfreev (slaves);
if (is_ata && !probe_ata (device, cancellable, error))
goto out;
}

ret = TRUE;

Expand Down
4 changes: 3 additions & 1 deletion src/udiskslinuxdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ struct _UDisksLinuxDevice
};

GType udisks_linux_device_get_type (void) G_GNUC_CONST;
UDisksLinuxDevice *udisks_linux_device_new_sync (GUdevDevice *udev_device);
UDisksLinuxDevice *udisks_linux_device_new_sync (GUdevDevice *udev_device,
GUdevClient *udev_client);
gboolean udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,
GUdevClient *udev_client,
GCancellable *cancellable,
GError **error);

Expand Down
2 changes: 1 addition & 1 deletion src/udiskslinuxdrive.c
Original file line number Diff line number Diff line change
Expand Up @@ -1593,7 +1593,7 @@ handle_power_off (UDisksDrive *_drive,
}
fd = -1;

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_dbus_method_invocation_return_error (invocation,
Expand Down
25 changes: 14 additions & 11 deletions src/udiskslinuxdriveata.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ udisks_linux_drive_ata_update (UDisksLinuxDriveAta *drive,
UDisksLinuxDriveObject *object)
{
UDisksLinuxDevice *device;
device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
goto out;

Expand Down Expand Up @@ -522,7 +522,7 @@ udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
goto out;
}

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_set_error_literal (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -701,7 +701,7 @@ udisks_linux_drive_ata_smart_selftest_sync (UDisksLinuxDriveAta *drive,
if (object == NULL)
goto out;

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_set_error_literal (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -782,7 +782,7 @@ handle_smart_update (UDisksDriveAta *_drive,
}

daemon = udisks_linux_drive_object_get_daemon (object);
block_object = udisks_linux_drive_object_get_block (object, TRUE);
block_object = udisks_linux_drive_object_get_block (object, FALSE);
if (block_object == NULL)
{
g_dbus_method_invocation_return_error (invocation,
Expand Down Expand Up @@ -916,7 +916,7 @@ handle_smart_selftest_abort (UDisksDriveAta *_drive,
}

daemon = udisks_linux_drive_object_get_daemon (object);
block_object = udisks_linux_drive_object_get_block (object, TRUE);
block_object = udisks_linux_drive_object_get_block (object, FALSE);
if (block_object == NULL)
{
g_dbus_method_invocation_return_error (invocation,
Expand Down Expand Up @@ -1140,7 +1140,7 @@ handle_smart_selftest_start (UDisksDriveAta *_drive,
}

daemon = udisks_linux_drive_object_get_daemon (object);
block_object = udisks_linux_drive_object_get_block (object, TRUE);
block_object = udisks_linux_drive_object_get_block (object, FALSE);
if (block_object == NULL)
{
g_dbus_method_invocation_return_error (invocation,
Expand Down Expand Up @@ -1291,7 +1291,7 @@ udisks_linux_drive_ata_get_pm_state (UDisksLinuxDriveAta *drive,

/* TODO: some SSD controllers may block for considerable time when trimming large amount of blocks */

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_set_error_literal (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -1451,7 +1451,7 @@ handle_pm_standby_wakeup (UDisksDriveAta *_drive,
invocation))
goto out;

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -1951,7 +1951,7 @@ udisks_linux_drive_ata_secure_erase_sync (UDisksLinuxDriveAta *drive,

daemon = udisks_linux_drive_object_get_daemon (object);

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_set_error (&local_error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -2336,6 +2336,7 @@ handle_smart_set_enabled (UDisksDriveAta *_drive,
UDisksLinuxDriveObject *object = NULL;
UDisksLinuxBlockObject *block_object = NULL;
UDisksDaemon *daemon;
UDisksLinuxProvider *provider;
GError *error = NULL;
UDisksLinuxDevice *device = NULL;
gint fd = -1;
Expand All @@ -2361,6 +2362,7 @@ handle_smart_set_enabled (UDisksDriveAta *_drive,
}

daemon = udisks_linux_drive_object_get_daemon (object);
provider = udisks_daemon_get_linux_provider (daemon);

error = NULL;
if (!udisks_daemon_util_get_caller_uid_sync (daemon,
Expand Down Expand Up @@ -2405,7 +2407,7 @@ handle_smart_set_enabled (UDisksDriveAta *_drive,
invocation))
goto out;

device = udisks_linux_drive_object_get_device (object, TRUE /* get_hw */);
device = udisks_linux_drive_object_get_device (object, FALSE /* get_hw */);
if (device == NULL)
{
g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
Expand Down Expand Up @@ -2448,7 +2450,8 @@ handle_smart_set_enabled (UDisksDriveAta *_drive,
}

/* Reread new IDENTIFY data */
if (!udisks_linux_device_reprobe_sync (device, NULL, &error))
if (!udisks_linux_device_reprobe_sync (device, udisks_linux_provider_get_udev_client (provider),
NULL, &error))
{
g_prefix_error (&error, "Error reprobing device: ");
g_dbus_method_invocation_take_error (invocation, error);
Expand Down
4 changes: 2 additions & 2 deletions src/udiskslinuxprovider.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ probe_request_thread_func (gpointer user_data)
continue;

/* probe the device - this may take a while */
request->udisks_device = udisks_linux_device_new_sync (request->udev_device);
request->udisks_device = udisks_linux_device_new_sync (request->udev_device, provider->gudev_client);

/* now that we've probed the device, post the request back to the main thread */
g_idle_add (on_idle_with_probed_uevent, request);
Expand Down Expand Up @@ -529,7 +529,7 @@ get_udisks_devices (UDisksLinuxProvider *provider)
GUdevDevice *device = G_UDEV_DEVICE (l->data);
if (!g_udev_device_get_is_initialized (device))
continue;
udisks_devices = g_list_prepend (udisks_devices, udisks_linux_device_new_sync (device));
udisks_devices = g_list_prepend (udisks_devices, udisks_linux_device_new_sync (device, provider->gudev_client));
}
udisks_devices = g_list_reverse (udisks_devices);
g_list_free_full (devices, g_object_unref);
Expand Down