[PATCH] Use internal pm check for smart poll
Phillip Susi
psusi at ubuntu.com
Tue Nov 5 01:49:30 CET 2013
libatasmart apparently has a bug where it will wake up a disk from
sleep just trying to open it, so use our own code to check the pm
state to avoid this.
Signed-off-by: Phillip Susi <psusi at ubuntu.com>
---
src/udiskslinuxdriveata.c | 101 ++++++++++++++++++++++++----------------------
1 file changed, 52 insertions(+), 49 deletions(-)
diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c
index 48cc6e6..1575b3d 100644
--- a/src/udiskslinuxdriveata.c
+++ b/src/udiskslinuxdriveata.c
@@ -427,6 +427,41 @@ selftest_status_to_string (SkSmartSelfTestExecutionStatus status)
return ret;
}
+static gboolean get_pm_state (UDisksLinuxDevice *device, GError **error, guchar *count)
+{
+ int fd = open (g_udev_device_get_device_file (device->udev_device), O_RDONLY|O_NONBLOCK);
+ gboolean rc = FALSE;
+ /* ATA8: 7.8 CHECK POWER MODE - E5h, Non-Data */
+ UDisksAtaCommandInput input = {.command = 0xe5};
+ UDisksAtaCommandOutput output = {0};
+
+ if (fd == -1)
+ {
+ g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
+ "Error opening device file %s: %m",
+ g_udev_device_get_device_file (device->udev_device));
+ goto out;
+ }
+
+ if (!udisks_ata_send_command_sync (fd,
+ -1,
+ UDISKS_ATA_COMMAND_PROTOCOL_NONE,
+ &input,
+ &output,
+ error))
+ {
+ g_prefix_error (error, "Error sending ATA command CHECK POWER MODE: ");
+ goto out;
+ }
+ /* count field is used for the state, see ATA8: table 102 */
+ *count = output.count;
+ rc = TRUE;
+ out:
+ if (fd != -1)
+ close(fd);
+ return rc;
+}
+
/**
* udisks_linux_drive_ata_refresh_smart_sync:
* @drive: The #UDisksLinuxDriveAta to refresh.
@@ -519,24 +554,10 @@ udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
}
else
{
- if (sk_disk_open (g_udev_device_get_device_file (device->udev_device), &d) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_open: %m");
- goto out;
- }
-
- if (sk_disk_check_sleep_mode (d, &awake) != 0)
- {
- g_set_error (error,
- UDISKS_ERROR,
- UDISKS_ERROR_FAILED,
- "sk_disk_check_sleep_mode: %m");
- goto out;
- }
-
+ guchar count;
+ if (!get_pm_state(device, error, &count))
+ goto out;
+ awake = count == 0xFF || count == 0x80;
/* don't wake up disk unless specically asked to */
if (nowakeup && !awake)
{
@@ -548,6 +569,15 @@ udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
}
}
+ if (sk_disk_open (g_udev_device_get_device_file (device->udev_device), &d) != 0)
+ {
+ g_set_error (error,
+ UDISKS_ERROR,
+ UDISKS_ERROR_FAILED,
+ "sk_disk_open: %m");
+ goto out;
+ }
+
if (sk_disk_smart_read_data (d) != 0)
{
g_set_error (error,
@@ -1184,10 +1214,10 @@ handle_pm_get_state (UDisksDriveAta *_drive,
UDisksLinuxDriveObject *object = NULL;
UDisksDaemon *daemon;
UDisksLinuxDevice *device = NULL;
- gint fd = -1;
GError *error = NULL;
const gchar *message;
const gchar *action_id;
+ guchar count;
object = udisks_daemon_util_dup_object (drive, &error);
if (object == NULL)
@@ -1244,38 +1274,11 @@ handle_pm_get_state (UDisksDriveAta *_drive,
"No udev device");
goto out;
}
-
- fd = open (g_udev_device_get_device_file (device->udev_device), O_RDONLY|O_NONBLOCK);
- if (fd == -1)
- {
- g_dbus_method_invocation_return_error (invocation, UDISKS_ERROR, UDISKS_ERROR_FAILED,
- "Error opening device file %s: %m",
- g_udev_device_get_device_file (device->udev_device));
- goto out;
- }
-
- {
- /* ATA8: 7.8 CHECK POWER MODE - E5h, Non-Data */
- UDisksAtaCommandInput input = {.command = 0xe5};
- UDisksAtaCommandOutput output = {0};
- if (!udisks_ata_send_command_sync (fd,
- -1,
- UDISKS_ATA_COMMAND_PROTOCOL_NONE,
- &input,
- &output,
- &error))
- {
- g_prefix_error (&error, "Error sending ATA command CHECK POWER MODE: ");
- g_dbus_method_invocation_take_error (invocation, error);
- goto out;
- }
- /* count field is used for the state, see ATA8: table 102 */
- udisks_drive_ata_complete_pm_get_state (_drive, invocation, output.count);
- }
+ if (get_pm_state (device, &error, &count))
+ udisks_drive_ata_complete_pm_get_state (_drive, invocation, count);
+ else g_dbus_method_invocation_take_error (invocation, error);
out:
- if (fd != -1)
- close (fd);
g_clear_object (&device);
g_clear_object (&object);
return TRUE; /* returning TRUE means that we handled the method invocation */
--
1.8.3.2
More information about the devkit-devel
mailing list