summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhillip Susi <psusi@ubuntu.com>2014-06-14 20:05:15 -0400
committerMartin Pitt <martin.pitt@ubuntu.com>2014-06-16 10:16:37 +0200
commit65c901f1ebbb1286c7f533abbd8716b5c7d7294e (patch)
treeb492743878b987265d2558c22541ca0753d1a6a2
parent10fb36a8d6f3a774bcf078931ce80627e06a6923 (diff)
Fix standby timers
If the drive was set to standby after >= 10 minutes of inactivity, it would never standby because udisks would check every 10 minutes to see if it was already in standby, and if not, update the SMART stats, which would reset the standby timer. This is especially problematic since many drives enforce a 10 minute minimum standby timer even if a lower value is specified. This patch checks the kernel IO stats to see if any other IO has been done on the drive since the last check, and if not, behaves as if the drive is already sleeping. Co-Authored-By: Martin Pitt <martin.pitt@ubuntu.com>
-rw-r--r--src/udiskslinuxdriveata.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/src/udiskslinuxdriveata.c b/src/udiskslinuxdriveata.c
index 9148dee..3b03874 100644
--- a/src/udiskslinuxdriveata.c
+++ b/src/udiskslinuxdriveata.c
@@ -88,6 +88,7 @@ struct _UDisksLinuxDriveAta
UDisksThreadedJob *selftest_job;
gboolean secure_erase_in_progress;
+ unsigned long drive_read, drive_write;
};
struct _UDisksLinuxDriveAtaClass
@@ -556,11 +557,39 @@ udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
else
{
guchar count;
+ gchar stat_path[PATH_MAX];
+ unsigned long drive_read, drive_write;
+ FILE *statf;
+ gboolean no_io = FALSE;
+
if (!get_pm_state(device, error, &count))
goto out;
awake = count == 0xFF || count == 0x80;
+
+ snprintf (stat_path, sizeof (stat_path), "%s/stat", g_udev_device_get_sysfs_path (device->udev_device));
+ statf = fopen (stat_path, "r");
+ if (statf == NULL)
+ {
+ udisks_warning ("Failed to open %s", stat_path);
+ }
+ else
+ {
+ int res = fscanf (statf, "%lu %*u %*u %*u %lu", &drive_read, &drive_write);
+ fclose (statf);
+
+ if (res == 2)
+ {
+ no_io = (drive_read == drive->drive_read && drive_write == drive->drive_write);
+ udisks_debug ("drive_read=%lu, drive_write=%lu, old drive_read=%lu, old drive_write=%lu\n",
+ drive_read, drive_write, drive->drive_read, drive->drive_write);
+ drive->drive_read = drive_read;
+ drive->drive_write = drive_write;
+ } else {
+ udisks_warning ("Failed to parse %s, only got %i items", stat_path, res);
+ }
+ }
/* don't wake up disk unless specically asked to */
- if (nowakeup && !awake)
+ if (nowakeup && (!awake || no_io))
{
g_set_error (error,
UDISKS_ERROR,