static void disk_ata_monitor_end(disk_t *disk) { ata_smart_attr_t smart[MAX_SMART_ATTRS]; int smart_num; int num_reallocs; int num_pending_reallocs; if (disk_smart_trip(&disk->dev) == 1) { ERROR("Disk has a SMART TRIP at the end of the test, it should be discarded!"); } else if (disk->state.ata.is_smart_tripped) { ERROR("Disk had a SMART TRIP during the test but it disappeared. This is super weird!!!"); } smart_num = disk_smart_attributes(&disk->dev, smart, ARRAY_SIZE(smart)); num_reallocs = ata_smart_get_num_reallocations(smart, smart_num, disk->state.ata.smart_table); num_pending_reallocs = ata_smart_get_num_pending_reallocations(smart, smart_num, disk->state.ata.smart_table); if (num_pending_reallocs > 0) { INFO("At the end of the test there are still some sectors pending reallocation, this is rather unexpected but can be lived with."); } if (num_reallocs > 1000) { INFO("Number of reallocated sectors is above 1000, you should probably stop using this disk!"); } }
void do_command(int fd) { unsigned char buf_thresh[512]; unsigned char buf_data[512]; if (!read_data(fd, buf_data, sizeof(buf_data))) return; if (!read_threshold(fd, buf_thresh, sizeof(buf_thresh))) return; const smart_table_t *table = smart_table_for_disk(NULL, NULL, NULL); ata_smart_attr_t attrs[MAX_SMART_ATTRS]; int num_attrs1 = ata_parse_ata_smart_read_data(buf_data, attrs, MAX_SMART_ATTRS); ata_smart_thresh_t thresholds[MAX_SMART_ATTRS]; int num_attrs2 = ata_parse_ata_smart_read_thresh(buf_thresh, thresholds, MAX_SMART_ATTRS); if (num_attrs1 != num_attrs2) { printf("Number of attributes in data (%d) and thresholds (%d) do not match\n", num_attrs1, num_attrs2); return; } printf("num attributes %d\n", num_attrs1); int i; for (i = 0; i < num_attrs1; i++) { const ata_smart_attr_t *attr = &attrs[i]; const ata_smart_thresh_t *thresh = &thresholds[i]; const smart_attr_t *attr_type = smart_attr_for_id(table, attr->id); printf("Attribute #%2d: id %3u %-40s status %04X val %3u min %3u thresh %3u raw %"PRIu64"\n", i, attr->id, attr_type ? attr_type->name : "Unknown", attr->status, attr->value, attr->min, thresh->threshold, attr->raw); } printf("\nKey attributes:\n"); { int min_temp, max_temp, cur_temp; cur_temp = ata_smart_get_temperature(attrs, num_attrs1, table, &min_temp, &max_temp); printf(" Temperature: %d (min=%d max=%d)\n", cur_temp, min_temp, max_temp); } { int minutes = -1; int hours; hours = ata_smart_get_power_on_hours(attrs, num_attrs1, table, &minutes); printf(" POH: %d (minutes: %d)\n", hours, minutes); } printf(" # Reallocations: %d\n", ata_smart_get_num_reallocations(attrs, num_attrs1, table)); printf(" # Pending Reallocations: %d\n", ata_smart_get_num_pending_reallocations(attrs, num_attrs1, table)); printf(" # CRC Errors: %d\n", ata_smart_get_num_crc_errors(attrs, num_attrs1, table)); }
static void ata_test_reallocs(disk_t *disk, ata_smart_attr_t *smart, int smart_num) { int num_reallocs; int num_pending_reallocs; num_reallocs = ata_smart_get_num_reallocations(smart, smart_num, disk->state.ata.smart_table); num_pending_reallocs = ata_smart_get_num_pending_reallocations(smart, smart_num, disk->state.ata.smart_table); if (num_reallocs > disk->state.ata.last_reallocs) { INFO("Number of reallocated sectors increased from %d to %d\n", disk->state.ata.last_reallocs, num_reallocs); disk->state.ata.last_reallocs = num_reallocs; } if (num_pending_reallocs != disk->state.ata.last_pending_reallocs) { INFO("Number of pending sectors for reallocations changed from %d to %d\n", disk->state.ata.last_pending_reallocs, num_pending_reallocs); disk->state.ata.last_pending_reallocs = num_pending_reallocs; } }
static void disk_ata_monitor_start(disk_t *disk) { if (disk_smart_trip(&disk->dev) == 1) { ERROR("Disk has a SMART TRIP at the start of the test, it should be discarded anyhow"); disk->state.ata.is_smart_tripped = true; } else { disk->state.ata.is_smart_tripped = false; } disk->state.ata.smart_table = smart_table_for_disk(disk->vendor, disk->model, disk->fw_rev); if (disk->state.ata.smart_table == NULL) ERROR("BUG! Failed to setup smart table for the disk."); disk->state.ata.smart_num = disk_smart_attributes(&disk->dev, disk->state.ata.smart, ARRAY_SIZE(disk->state.ata.smart)); if (disk->state.ata.smart_num > 0) { // First look at temperatures int min_temp = -1; int max_temp = -1; int temp = ata_smart_get_temperature(disk->state.ata.smart, disk->state.ata.smart_num, disk->state.ata.smart_table, &min_temp, &max_temp); disk->state.ata.last_temp = temp; if (min_temp > 0 || max_temp > 0) INFO("Disk start temperature is %d (lifetime min %d and lifetime max %d)", temp, min_temp, max_temp); else INFO("Disk start temperature is %d", temp); // First look on reallocations disk->state.ata.last_reallocs = ata_smart_get_num_reallocations(disk->state.ata.smart, disk->state.ata.smart_num, disk->state.ata.smart_table); disk->state.ata.last_pending_reallocs = ata_smart_get_num_pending_reallocations(disk->state.ata.smart, disk->state.ata.smart_num, disk->state.ata.smart_table); // Now take a first look at the CRC error counters disk->state.ata.last_crc_errors = ata_smart_get_num_crc_errors(disk->state.ata.smart, disk->state.ata.smart_num, disk->state.ata.smart_table); } else { ERROR("Failed to read SMART attributes from device"); } }