📄 ataprint.cpp
字号:
// print data structure revision number pout("SMART Selective self-test log data structure revision number %d\n",(int)log->logversion); if (1 != log->logversion) pout("Warning: ATA Specification requires selective self-test log data structure revision number = 1\n"); switch((sv->self_test_exec_status)>>4){ case 0:msg="Completed"; break; case 1:msg="Aborted_by_host"; break; case 2:msg="Interrupted"; break; case 3:msg="Fatal_error"; break; case 4:msg="Completed_unknown_failure"; break; case 5:msg="Completed_electrical_failure"; break; case 6:msg="Completed_servo/seek_failure"; break; case 7:msg="Completed_read_failure"; break; case 8:msg="Completed_handling_damage??"; break; case 15:msg="Self_test_in_progress"; break; default:msg="Unknown_status "; break; } // find the number of columns needed for printing. If in use, the // start/end of span being read-scanned... if (log->currentspan>5) { maxl=current; maxr=currentend; } for (i=0; i<5; i++) { uint64_t start=log->span[i].start; uint64_t end =log->span[i].end; // ... plus max start/end of each of the five test spans. if (start>maxl) maxl=start; if (end > maxr) maxr=end; } // we need at least 7 characters wide fields to accomodate the // labels if ((field1=snprintf(tmp,64, "%"PRIu64, maxl))<7) field1=7; if ((field2=snprintf(tmp,64, "%"PRIu64, maxr))<7) field2=7; // now print the five test spans pout(" SPAN %*s %*s CURRENT_TEST_STATUS\n", field1, "MIN_LBA", field2, "MAX_LBA"); for (i=0; i<5; i++) { uint64_t start=log->span[i].start; uint64_t end=log->span[i].end; if ((i+1)==(int)log->currentspan) // this span is currently under test pout(" %d %*"PRIu64" %*"PRIu64" %s [%01d0%% left] (%"PRIu64"-%"PRIu64")\n", i+1, field1, start, field2, end, msg, (int)(sv->self_test_exec_status & 0xf), current, currentend); else // this span is not currently under test pout(" %d %*"PRIu64" %*"PRIu64" Not_testing\n", i+1, field1, start, field2, end); } // if we are currently read-scanning, print LBAs and the status of // the read scan if (log->currentspan>5) pout("%5d %*"PRIu64" %*"PRIu64" Read_scanning %s\n", (int)log->currentspan, field1, current, field2, currentend, OfflineDataCollectionStatus(sv->offline_data_collection_status)); /* Print selective self-test flags. Possible flag combinations are (numbering bits from 0-15): Bit-1 Bit-3 Bit-4 Scan Pending Active 0 * * Don't scan 1 0 0 Will carry out scan after selective test 1 1 0 Waiting to carry out scan after powerup 1 0 1 Currently scanning 1 1 1 Currently scanning */ pout("Selective self-test flags (0x%x):\n", (unsigned int)log->flags); if (log->flags & SELECTIVE_FLAG_DOSCAN) { if (log->flags & SELECTIVE_FLAG_ACTIVE) pout(" Currently read-scanning the remainder of the disk.\n"); else if (log->flags & SELECTIVE_FLAG_PENDING) pout(" Read-scan of remainder of disk interrupted; will resume %d min after power-up.\n", (int)log->pendingtime); else pout(" After scanning selected spans, read-scan remainder of disk.\n"); } else pout(" After scanning selected spans, do NOT read-scan remainder of disk.\n"); // print pending time pout("If Selective self-test is pending on power-up, resume after %d minute delay.\n", (int)log->pendingtime); return; }// return value is:// bottom 8 bits: number of entries found where self-test showed an error// remaining bits: if nonzero, power on hours of last self-test where error was foundint ataPrintSmartSelfTestlog(struct ata_smart_selftestlog *data,int allentries){ int i,j,noheaderprinted=1; int retval=0, hours=0, testno=0; if (allentries) pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber); if ((data->revnumber!=0x0001) && allentries && con->fixfirmwarebug != FIX_SAMSUNG) pout("Warning: ATA Specification requires self-test log structure revision number = 1\n"); if (data->mostrecenttest==0){ if (allentries) pout("No self-tests have been logged. [To run self-tests, use: smartctl -t]\n\n"); return 0; } // print log for (i=20;i>=0;i--){ struct ata_smart_selftestlog_struct *log; // log is a circular buffer j=(i+data->mostrecenttest)%21; log=data->selftest_struct+j; if (nonempty((unsigned char*)log,sizeof(*log))){ char *msgtest,*msgstat,percent[64],firstlba[64]; int errorfound=0; // count entry based on non-empty structures -- needed for // Seagate only -- other vendors don't have blank entries 'in // the middle' testno++; // test name switch(log->selftestnumber){ case 0: msgtest="Offline "; break; case 1: msgtest="Short offline "; break; case 2: msgtest="Extended offline "; break; case 3: msgtest="Conveyance offline "; break; case 4: msgtest="Selective offline "; break; case 127: msgtest="Abort offline test "; break; case 129: msgtest="Short captive "; break; case 130: msgtest="Extended captive "; break; case 131: msgtest="Conveyance captive "; break; case 132: msgtest="Selective captive "; break; default: if ( log->selftestnumber>=192 || (log->selftestnumber>= 64 && log->selftestnumber<=126)) msgtest="Vendor offline "; else msgtest="Reserved offline "; } // test status switch((log->selfteststatus)>>4){ case 0:msgstat="Completed without error "; break; case 1:msgstat="Aborted by host "; break; case 2:msgstat="Interrupted (host reset) "; break; case 3:msgstat="Fatal or unknown error "; errorfound=1; break; case 4:msgstat="Completed: unknown failure "; errorfound=1; break; case 5:msgstat="Completed: electrical failure"; errorfound=1; break; case 6:msgstat="Completed: servo/seek failure"; errorfound=1; break; case 7:msgstat="Completed: read failure "; errorfound=1; break; case 8:msgstat="Completed: handling damage?? "; errorfound=1; break; case 15:msgstat="Self-test routine in progress"; break; default:msgstat="Unknown/reserved test status "; } retval+=errorfound; sprintf(percent,"%1d0%%",(log->selfteststatus)&0xf); // T13/1321D revision 1c: (Data structure Rev #1) //The failing LBA shall be the LBA of the uncorrectable sector //that caused the test to fail. If the device encountered more //than one uncorrectable sector during the test, this field //shall indicate the LBA of the first uncorrectable sector //encountered. If the test passed or the test failed for some //reason other than an uncorrectable sector, the value of this //field is undefined. // This is true in ALL ATA-5 specs if (!errorfound || log->lbafirstfailure==0xffffffff || log->lbafirstfailure==0x00000000) sprintf(firstlba,"%s","-"); else sprintf(firstlba,"%u",log->lbafirstfailure); // print out a header if needed if (noheaderprinted && (allentries || errorfound)){ pout("Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error\n"); noheaderprinted=0; } // print out an entry, either if we are printing all entries OR // if an error was found if (allentries || errorfound) pout("#%2d %s %s %s %8d %s\n", testno, msgtest, msgstat, percent, (int)log->timestamp, firstlba); // keep track of time of most recent error if (errorfound && !hours) hours=log->timestamp; } } if (!allentries && retval) pout("\n"); hours = hours << 8; return (retval | hours);}void ataPseudoCheckSmart ( struct ata_smart_values *data, struct ata_smart_thresholds_pvt *thresholds) { int i; int failed = 0; for (i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++) { if (data->vendor_attributes[i].id && thresholds->thres_entries[i].id && ATTRIBUTE_FLAGS_PREFAILURE(data->vendor_attributes[i].flags) && (data->vendor_attributes[i].current <= thresholds->thres_entries[i].threshold) && (thresholds->thres_entries[i].threshold != 0xFE)){ pout("Attribute ID %d Failed\n",(int)data->vendor_attributes[i].id); failed = 1; } } pout("%s\n", ( failed )? "SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA": "SMART overall-health self-assessment test result: PASSED");}// Format SCT Temperature valuestatic const char * sct_ptemp(signed char x, char * buf){ if (x == -128 /*0x80 = unknown*/) strcpy(buf, " ?"); else sprintf(buf, "%2d", x); return buf;}static const char * sct_pbar(int x, char * buf){ if (x <= 19) x = 0; else x -= 19; bool ov = false; if (x > 40) { x = 40; ov = true; } if (x > 0) { memset(buf, '*', x); if (ov) buf[x-1] = '+'; buf[x] = 0; } else { buf[0] = '-'; buf[1] = 0; } return buf;}static const char * sct_device_state_msg(unsigned char state){ switch (state) { case 0: return "Active"; case 1: return "Stand-by"; case 2: return "Sleep"; case 3: return "DST executing in background"; case 4: return "SMART Off-line Data Collection executing in background"; case 5: return "SCT command executing in background"; default:return "Unknown"; }}// Print SCT Statusstatic int ataPrintSCTStatus(const ata_sct_status_response * sts){ pout("SCT Status Version: %u\n", sts->format_version); pout("SCT Version (vendor specific): %u (0x%04x)\n", sts->sct_version, sts->sct_version); pout("SCT Support Level: %u\n", sts->sct_spec); pout("Device State: %s (%u)\n", sct_device_state_msg(sts->device_state), sts->device_state); char buf1[20], buf2[20]; if ( !sts->min_temp && !sts->life_min_temp && !sts->byte205 && !sts->under_limit_count && !sts->over_limit_count ) { // "Reserved" fields not set, assume "old" format version 2 // Table 11 of T13/1701DT Revision 5 // Table 54 of T13/1699-D Revision 3e pout("Current Temperature: %s Celsius\n", sct_ptemp(sts->hda_temp, buf1)); pout("Power Cycle Max Temperature: %s Celsius\n", sct_ptemp(sts->max_temp, buf2)); pout("Lifetime Max Temperature: %s Celsius\n", sct_ptemp(sts->life_max_temp, buf2)); } else { // Assume "new" format version 2 or version 3 // T13/e06152r0-3 (Additional SCT Temperature Statistics) // Table 60 of T13/1699-D Revision 3f pout("Current Temperature: %s Celsius\n", sct_ptemp(sts->hda_temp, buf1)); pout("Power Cycle Min/Max Temperature: %s/%s Celsius\n", sct_ptemp(sts->min_temp, buf1), sct_ptemp(sts->max_temp, buf2)); pout("Lifetime Min/Max Temperature: %s/%s Celsius\n", sct_ptemp(sts->life_min_temp, buf1), sct_ptemp(sts->life_max_temp, buf2)); if (sts->byte205) // e06152r0-2, removed in e06152r3 pout("Lifetime Average Temperature: %s Celsius\n", sct_ptemp((signed char)sts->byte205, buf1)); pout("Under/Over Temperature Limit Count: %2u/%u\n", sts->under_limit_count, sts->over_limit_count); } return 0;}// Print SCT Temperature History Tablestatic int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh){ char buf1[20], buf2[80]; pout("SCT Temperature History Version: %u\n", tmh->format_version); pout("Temperature Sampling Period: %u minute%s\n", tmh->sampling_period, (tmh->sampling_period==1?"":"s")); pout("Temperature Logging Interval: %u minute%s\n", tmh->interval, (tmh->interval==1?"":"s")); pout("Min/Max recommended Temperature: %s/%s Celsius\n", sct_ptemp(tmh->min_op_limit, buf1), sct_ptemp(tmh->max_op_limit, buf2)); pout("Min/Max Temperature Limit: %s/%s Celsius\n", sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2)); pout("Temperature History Size (Index): %u (%u)\n", tmh->cb_size, tmh->cb_index); if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) { pout("Error invalid Temperature History Size or Index\n"); return 0; } // Print table pout("\nIndex Estimated Time Temperature Celsius\n"); unsigned n = 0, i = (tmh->cb_index+1) % tmh->cb_size; unsigned interval = (tmh->interval > 0 ? tmh->interval : 1); time_t t = time(0) - (tmh->cb_size-1) * interval * 60; t -= t % (interval * 60); while (n < tmh->cb_size) { // Find range of identical temperatures unsigned n1 = n, n2 = n+1, i2 = (i+1) % tmh->cb_size; while (n2 < tmh->cb_size && tmh->cb[i2] == tmh->cb[i]) { n2++; i2 = (i2+1) % tmh->cb_size; } // Print range while (n < n2) { if (n == n1 || n == n2-1 || n2 <= n1+3) { char date[30]; // TODO: Don't print times < boot time strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&t)); pout(" %3u %s %s %s\n", i, date, sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf2)); } else if (n == n1+1) { pout(" ... ..(%3u skipped). .. %s\n", n2-n1-2, sct_pbar(tmh->cb[i], buf2)); } t += interval * 60; i = (i+1) % tmh->cb_size; n++; } } //assert(n == tmh->cb_size && i == (tmh->cb_index+1) % tmh->cb_size); return 0;}// Compares failure type to policy in effect, and either exits or// simply returns to the calling routine.void failuretest(int type, int returnvalue){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -