Skip to content

Commit

Permalink
Merge pull request #1312 from tbzatek/ata-cmd-2
Browse files Browse the repository at this point in the history
udiskslinuxdriveata: Prefer udev ID_ATA_* attributes
  • Loading branch information
tbzatek authored Oct 1, 2024
2 parents 85d6fac + 464db39 commit fe64bca
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 45 deletions.
6 changes: 6 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ if test "x$enable_daemon" = "xyes"; then
AC_SUBST(GUDEV_CFLAGS)
AC_SUBST(GUDEV_LIBS)

PKG_CHECK_MODULES(UDEV, [udev >= 257], [have_udev_257=yes], [have_udev_257=no])
if test "x$have_udev_257" = "xyes"; then
AC_DEFINE([HAVE_UDEV_257], 1, [Define to 1 if udev >= 257 is available])
fi
AC_SUBST(HAVE_UDEV_257)

PKG_CHECK_MODULES(GMODULE, [gmodule-2.0])
AC_SUBST(GMODULE_CFLAGS)
AC_SUBST(GMODULE_LIBS)
Expand Down
19 changes: 16 additions & 3 deletions src/udiskslinuxdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ udisks_linux_device_class_init (UDisksLinuxDeviceClass *klass)
/* ---------------------------------------------------------------------------------------------------- */

static gboolean probe_ata (UDisksLinuxDevice *device,
gboolean force_probe,
GCancellable *cancellable,
GError **error);

Expand Down Expand Up @@ -176,7 +177,7 @@ udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,
!g_udev_device_has_property (device->udev_device, "ID_USB_MODEL") &&
!udisks_linux_device_is_mpath_device_path (device))
{
if (!probe_ata (device, cancellable, error))
if (!probe_ata (device, FALSE, cancellable, error))
goto out;
}
else
Expand Down Expand Up @@ -250,7 +251,7 @@ udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,
break;
}
g_strfreev (slaves);
if (is_ata && !probe_ata (device, cancellable, error))
if (is_ata && !probe_ata (device, TRUE, cancellable, error))
goto out;
}

Expand All @@ -264,6 +265,7 @@ udisks_linux_device_reprobe_sync (UDisksLinuxDevice *device,

static gboolean
probe_ata (UDisksLinuxDevice *device,
gboolean force_probe,
GCancellable *cancellable,
GError **error)
{
Expand All @@ -273,6 +275,18 @@ probe_ata (UDisksLinuxDevice *device,
UDisksAtaCommandInput input = {0};
UDisksAtaCommandOutput output = {0};

if (!force_probe
#ifndef HAVE_UDEV_257
/* added in https://github.com/systemd/systemd/pull/34343,
* skip probing if present (e.g. backported)
*/
&& g_udev_device_has_property (device->udev_device, "ID_ATA_READ_LOOKAHEAD")
#else
/* udev >= 257 carries everything we need, no need for explicit probing */
#endif
)
return TRUE;

device_file = g_udev_device_get_device_file (device->udev_device);
fd = open (device_file, O_RDONLY|O_NONBLOCK);
if (fd == -1)
Expand All @@ -283,7 +297,6 @@ probe_ata (UDisksLinuxDevice *device,
goto out;
}


if (ioctl (fd, CDROM_GET_CAPABILITY, NULL) == -1)
{
/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In */
Expand Down
4 changes: 3 additions & 1 deletion src/udiskslinuxdrive.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,9 @@ set_rotation_rate (UDisksDrive *iface,
else
{
rate = -1;
if (device->ata_identify_device_data != NULL)
if (g_udev_device_has_property (device->udev_device, "ID_ATA_ROTATION_RATE_RPM"))
rate = g_udev_device_get_property_as_int (device->udev_device, "ID_ATA_ROTATION_RATE_RPM");
else if (device->ata_identify_device_data != NULL)
{
guint word_217 = 0;

Expand Down
123 changes: 83 additions & 40 deletions src/udiskslinuxdriveata.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,16 @@ update_smart (UDisksLinuxDriveAta *drive,
guint16 word_85 = 0;

#ifdef HAVE_SMART
/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);
supported = word_82 & (1<<0);
enabled = word_85 & (1<<0);
#else
supported = enabled = FALSE;
supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_SMART");
enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_SMART_ENABLED");
if (!supported && device->ata_identify_device_data)
{
/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);
supported = word_82 & (1<<0);
enabled = word_85 & (1<<0);
}
#endif

G_LOCK (object_lock);
Expand Down Expand Up @@ -277,25 +280,52 @@ update_pm (UDisksLinuxDriveAta *drive,
guint16 word_86 = 0;
guint16 word_94 = 0;

/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_83 = udisks_ata_identify_get_word (device->ata_identify_device_data, 83);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);
word_86 = udisks_ata_identify_get_word (device->ata_identify_device_data, 86);
word_94 = udisks_ata_identify_get_word (device->ata_identify_device_data, 94);

pm_supported = word_82 & (1<<3);
pm_enabled = word_85 & (1<<3);
apm_supported = word_83 & (1<<3);
apm_enabled = word_86 & (1<<3);
aam_supported = word_83 & (1<<9);
aam_enabled = word_86 & (1<<9);
if (aam_supported)
aam_vendor_recommended_value = (word_94 >> 8);
write_cache_supported = word_82 & (1<<5);
write_cache_enabled = word_85 & (1<<5);
read_lookahead_supported = word_82 & (1<<6);
read_lookahead_enabled = word_85 & (1<<6);
pm_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_PM");
pm_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_PM_ENABLED");
apm_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_APM");
apm_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_APM_ENABLED");
aam_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_AAM");
aam_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_AAM_ENABLED");
write_cache_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_WRITE_CACHE");
write_cache_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_WRITE_CACHE_ENABLED");
read_lookahead_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_READ_LOOKAHEAD");
read_lookahead_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_READ_LOOKAHEAD_ENABLED");
aam_vendor_recommended_value = g_udev_device_get_property_as_int (device->udev_device, "ID_ATA_FEATURE_SET_AAM_VENDOR_RECOMMENDED_VALUE");

if (device->ata_identify_device_data)
{
/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);

/* available in udev since < 2012 */
if (!g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA"))
{
word_83 = udisks_ata_identify_get_word (device->ata_identify_device_data, 83);
word_86 = udisks_ata_identify_get_word (device->ata_identify_device_data, 86);
word_94 = udisks_ata_identify_get_word (device->ata_identify_device_data, 94);

pm_supported = word_82 & (1<<3);
pm_enabled = word_85 & (1<<3);
apm_supported = word_83 & (1<<3);
apm_enabled = word_86 & (1<<3);
aam_supported = word_83 & (1<<9);
aam_enabled = word_86 & (1<<9);
if (aam_supported)
aam_vendor_recommended_value = (word_94 >> 8);
write_cache_supported = word_82 & (1<<5);
write_cache_enabled = word_85 & (1<<5);
}

/* added recently, unable to distinguish between "not supported by device"
* and "not implemented by udev"
*/
if (!read_lookahead_supported)
{
read_lookahead_supported = word_82 & (1<<6);
read_lookahead_enabled = word_85 & (1<<6);
}
}

g_object_freeze_notify (G_OBJECT (drive));
udisks_drive_ata_set_pm_supported (UDISKS_DRIVE_ATA (drive), !!pm_supported);
Expand Down Expand Up @@ -329,21 +359,31 @@ update_security (UDisksLinuxDriveAta *drive,
guint16 word_90 = 0;
guint16 word_128 = 0;

/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);
word_89 = udisks_ata_identify_get_word (device->ata_identify_device_data, 89);
word_90 = udisks_ata_identify_get_word (device->ata_identify_device_data, 90);
word_128 = udisks_ata_identify_get_word (device->ata_identify_device_data, 128);

security_supported = word_82 & (1<<1);
security_enabled = word_85 & (1<<1);
if (security_supported)
{
erase_unit = (word_89 & 0xff) * 2;
enhanced_erase_unit = (word_90 & 0xff) * 2;
security_supported = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_SECURITY");
security_enabled = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_SECURITY_ENABLED");
erase_unit = g_udev_device_get_property_as_int (device->udev_device, "ID_ATA_FEATURE_SET_SECURITY_ERASE_UNIT_MIN");
enhanced_erase_unit = g_udev_device_get_property_as_int (device->udev_device, "ID_ATA_FEATURE_SET_SECURITY_ENHANCED_ERASE_UNIT_MIN");
frozen = g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA_FEATURE_SET_SECURITY_FROZEN");

if (!g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA")
&& device->ata_identify_device_data)
{
/* ATA8: 7.16 IDENTIFY DEVICE - ECh, PIO Data-In - Table 29 IDENTIFY DEVICE data */
word_82 = udisks_ata_identify_get_word (device->ata_identify_device_data, 82);
word_85 = udisks_ata_identify_get_word (device->ata_identify_device_data, 85);
word_89 = udisks_ata_identify_get_word (device->ata_identify_device_data, 89);
word_90 = udisks_ata_identify_get_word (device->ata_identify_device_data, 90);
word_128 = udisks_ata_identify_get_word (device->ata_identify_device_data, 128);

security_supported = word_82 & (1<<1);
security_enabled = word_85 & (1<<1);
if (security_supported)
{
erase_unit = (word_89 & 0xff) * 2;
enhanced_erase_unit = (word_90 & 0xff) * 2;
}
frozen = word_128 & (1<<3);
}
frozen = word_128 & (1<<3);

g_object_freeze_notify (G_OBJECT (drive));
/* TODO: export Security{Supported,Enabled} properties
Expand Down Expand Up @@ -1314,6 +1354,9 @@ handle_smart_set_enabled (UDisksDriveAta *_drive,
}
}

udisks_linux_block_object_trigger_uevent_sync (UDISKS_LINUX_BLOCK_OBJECT (block_object),
UDISKS_DEFAULT_WAIT_TIMEOUT);

/* Reread new IDENTIFY data */
if (!udisks_linux_device_reprobe_sync (device,
udisks_linux_provider_get_udev_client (provider),
Expand Down
3 changes: 2 additions & 1 deletion src/udiskslinuxdriveobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,8 @@ drive_ata_check (UDisksObject *object)
goto out;

device = drive_object->devices->data;
if (device->ata_identify_device_data != NULL || device->ata_identify_packet_device_data != NULL)
if (g_udev_device_get_property_as_boolean (device->udev_device, "ID_ATA") ||
device->ata_identify_device_data != NULL || device->ata_identify_packet_device_data != NULL)
ret = TRUE;

out:
Expand Down

0 comments on commit fe64bca

Please sign in to comment.