Skip to content

Commit

Permalink
Merge pull request #949 from tbzatek/fs-size-lazy
Browse files Browse the repository at this point in the history
udiskslinuxfilesystem: Make 'size' property retrieval on demand
  • Loading branch information
tbzatek committed Jan 17, 2022
2 parents 806a684 + 9a2a96b commit d65afca
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 82 deletions.
3 changes: 2 additions & 1 deletion doc/udisks2-sections.txt.daemon.sections.in
Expand Up @@ -161,7 +161,6 @@ udisks_linux_drive_ata_smart_selftest_sync
udisks_linux_drive_ata_apply_configuration
udisks_linux_drive_ata_secure_erase_sync
udisks_linux_drive_ata_get_pm_state
UDISKS_LINUX_DRIVE_ATA_IS_AWAKE
<SUBSECTION Standard>
UDISKS_LINUX_DRIVE_ATA
UDISKS_IS_LINUX_DRIVE_ATA
Expand Down Expand Up @@ -269,6 +268,8 @@ UDisksAtaCommandProtocol
UDisksAtaCommandInput
UDisksAtaCommandOutput
udisks_ata_send_command_sync
udisks_ata_get_pm_state
UDISKS_ATA_PM_STATE_AWAKE
</SECTION>

<SECTION>
Expand Down
62 changes: 62 additions & 0 deletions src/udisksata.c
Expand Up @@ -308,3 +308,65 @@ udisks_ata_send_command_sync (gint fd,
out:
return ret;
}

/**
* udisks_ata_get_pm_state:
* @device: ATA drive block device path.
* @error: Return location for error.
* @pm_state: Return location for the current power state value.
*
* Get the current power mode state.
*
* The format of @pm_state is the result obtained from sending the
* ATA command `CHECK POWER MODE` to the drive.
*
* Known values include:
* - `0x00`: Device is in PM2: Standby state.
* - `0x40`: Device is in the PM0: Active state, the NV Cache power mode is enabled, and the spindle is spun down or spinning down.
* - `0x41`: Device is in the PM0: Active state, the NV Cache power mode is enabled, and the spindle is spun up or spinning up.
* - `0x80`: Device is in PM1: Idle state.
* - `0xff`: Device is in the PM0: Active state or PM1: Idle State.
*
* Typically user interfaces will report "Drive is spun down" if @pm_state is
* 0x00 and "Drive is spun up" otherwise.
*
* Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
*/
gboolean
udisks_ata_get_pm_state (const gchar *device, GError **error, guchar *count)
{
int fd;
gboolean rc = FALSE;
/* ATA8: 7.8 CHECK POWER MODE - E5h, Non-Data */
UDisksAtaCommandInput input = {.command = 0xe5};
UDisksAtaCommandOutput output = {0};

g_warn_if_fail (device != NULL);

fd = open (device, O_RDONLY|O_NONBLOCK);
if (fd == -1)
{
g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
"Error opening device file %s while getting PM state: %m",
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;
}
13 changes: 13 additions & 0 deletions src/udisksata.h
Expand Up @@ -73,13 +73,26 @@ struct _UDisksAtaCommandOutput
guchar *buffer;
};

/**
* UDISKS_ATA_PM_STATE_AWAKE:
* @pm_state: The power state value.
*
* Decodes the power state value as returned by #udisks_ata_get_pm_state.
*
* Returns: %TRUE when the drive is awake, %FALSE when sleeping.
*/
#define UDISKS_ATA_PM_STATE_AWAKE(pm_state) (pm_state >= 0x41)

gboolean udisks_ata_send_command_sync (gint fd,
gint timeout_msec,
UDisksAtaCommandProtocol protocol,
UDisksAtaCommandInput *input,
UDisksAtaCommandOutput *output,
GError **error);

gboolean udisks_ata_get_pm_state (const gchar *device,
GError **error,
guchar *count);

G_END_DECLS

Expand Down
41 changes: 2 additions & 39 deletions src/udiskslinuxdriveata.c
Expand Up @@ -437,43 +437,6 @@ selftest_status_to_string (SkSmartSelfTestExecutionStatus status)
return ret;
}

static gboolean
get_pm_state (UDisksLinuxDevice *device, GError **error, guchar *count)
{
int fd;
gboolean rc = FALSE;
/* ATA8: 7.8 CHECK POWER MODE - E5h, Non-Data */
UDisksAtaCommandInput input = {.command = 0xe5};
UDisksAtaCommandOutput output = {0};

fd = open (g_udev_device_get_device_file (device->udev_device), O_RDONLY|O_NONBLOCK);
if (fd == -1)
{
g_set_error (error, UDISKS_ERROR, UDISKS_ERROR_FAILED,
"Error opening device file %s while getting PM state: %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;
}

static gboolean update_io_stats (UDisksLinuxDriveAta *drive, UDisksLinuxDevice *device)
{
const gchar *drivepath = g_udev_device_get_sysfs_path (device->udev_device);
Expand Down Expand Up @@ -603,7 +566,7 @@ udisks_linux_drive_ata_refresh_smart_sync (UDisksLinuxDriveAta *drive,
gboolean noio = FALSE;
if (drive->standby_enabled)
noio = update_io_stats (drive, device);
if (!get_pm_state (device, error, &count))
if (!udisks_ata_get_pm_state (g_udev_device_get_device_file (device->udev_device), error, &count))
goto out;
awake = count == 0xFF || count == 0x80;
/* don't wake up disk unless specically asked to */
Expand Down Expand Up @@ -1322,7 +1285,7 @@ udisks_linux_drive_ata_get_pm_state (UDisksLinuxDriveAta *drive,
goto out;
}

ret = get_pm_state (device, error, pm_state);
ret = udisks_ata_get_pm_state (g_udev_device_get_device_file (device->udev_device), error, pm_state);

out:
g_clear_object (&device);
Expand Down
10 changes: 0 additions & 10 deletions src/udiskslinuxdriveata.h
Expand Up @@ -29,16 +29,6 @@ G_BEGIN_DECLS
#define UDISKS_LINUX_DRIVE_ATA(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UDISKS_TYPE_LINUX_DRIVE_ATA, UDisksLinuxDriveAta))
#define UDISKS_IS_LINUX_DRIVE_ATA(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UDISKS_TYPE_LINUX_DRIVE_ATA))

/**
* UDISKS_LINUX_DRIVE_ATA_IS_AWAKE:
* @pm_state: The power state value.
*
* Decodes the power state value as returned by #udisks_linux_drive_ata_get_pm_state.
*
* Returns: %TRUE when the drive is awake, %FALSE when sleeping.
*/
#define UDISKS_LINUX_DRIVE_ATA_IS_AWAKE(pm_state) (pm_state >= 0x41)

GType udisks_linux_drive_ata_get_type (void) G_GNUC_CONST;
UDisksDriveAta *udisks_linux_drive_ata_new (void);
gboolean udisks_linux_drive_ata_update (UDisksLinuxDriveAta *drive,
Expand Down

0 comments on commit d65afca

Please sign in to comment.