diff options
author | Phillip Susi <psusi@ubuntu.com> | 2014-06-14 20:05:15 -0400 |
---|---|---|
committer | Martin Pitt <martin.pitt@ubuntu.com> | 2014-06-16 10:16:37 +0200 |
commit | 65c901f1ebbb1286c7f533abbd8716b5c7d7294e (patch) | |
tree | b492743878b987265d2558c22541ca0753d1a6a2 | |
parent | 10fb36a8d6f3a774bcf078931ce80627e06a6923 (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.c | 31 |
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, |