Ticket #1427: acs4_sct_ert_enhancements_v0.patch
File acs4_sct_ert_enhancements_v0.patch, 14.9 KB (added by , 4 years ago) |
---|
-
atacmds.cpp
diff --git a/atacmds.cpp b/atacmds.cpp index b0b1d2b..fdb33cb 100644
a b int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten 2414 2414 2415 2415 // Get/Set SCT Error Recovery Control 2416 2416 static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, 2417 bool set, unsigned short & time_limit) 2417 bool set, unsigned short & time_limit, 2418 bool power_on, bool mfg_default) 2418 2419 { 2419 2420 // Check initial status 2420 2421 ata_sct_status_response sts; … … static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 2432 2433 ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd)); 2433 2434 // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK) 2434 2435 cmd.action_code = 3; // Error Recovery Control command 2435 cmd.function_code = (set ? 1 : 2); // 1=Set timer, 2=Get timer 2436 2437 // 1=Set timer, 2=Get timer, 3=Set Power-on timer, 4=Get Power-on timer, 5=Restore mfg default 2438 if (mfg_default) { 2439 cmd.function_code = 5; 2440 } else if (power_on) { 2441 cmd.function_code = (set ? 3 : 4); 2442 } else { 2443 cmd.function_code = (set ? 1 : 2); 2444 } 2445 unsigned short saved_function_code = cmd.function_code; 2446 2436 2447 cmd.selection_code = type; // 1=Read timer, 2=Write timer 2437 2448 if (set) 2438 2449 cmd.time_limit = time_limit; … … static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 2469 2480 if (ataReadSCTStatus(device, &sts)) 2470 2481 return -1; 2471 2482 2472 if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == (set ? 1 : 2))) {2483 if (!(sts.ext_status_code == 0 && sts.action_code == 3 && sts.function_code == saved_function_code)) { 2473 2484 pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n", 2474 2485 sts.ext_status_code, sts.action_code, sts.function_code); 2475 2486 return -1; … … static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 2498 2509 } 2499 2510 2500 2511 // Get SCT Error Recovery Control 2501 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit )2512 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on) 2502 2513 { 2503 return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit );2514 return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit, power_on, false); 2504 2515 } 2505 2516 2506 2517 // Set SCT Error Recovery Control 2507 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit) 2518 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit, 2519 bool power_on, bool mfg_default) 2508 2520 { 2509 return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit );2521 return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit, power_on, mfg_default); 2510 2522 } 2511 2523 2512 2524 -
atacmds.h
diff --git a/atacmds.h b/atacmds.h index 94c9ae9..9e81377 100644
a b STATIC_ASSERT(sizeof(ata_sct_status_response) == 512); 545 545 struct ata_sct_error_recovery_control_command 546 546 { 547 547 unsigned short action_code; // 3 = Error Recovery Control 548 unsigned short function_code; // 1 = Set , 2 = Return548 unsigned short function_code; // 1 = Set Current, 2 = Return Current, 3 = Set Power-on, 4 = Return Power-on, 5 = Restore Default 549 549 unsigned short selection_code; // 1 = Read Timer, 2 = Write Timer 550 550 unsigned short time_limit; // If set: Recovery time limit in 100ms units 551 551 unsigned short words004_255[252]; // reserved … … int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * 792 792 int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent); 793 793 794 794 // Get/Set SCT Error Recovery Control 795 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit );796 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit );795 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on); 796 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default); 797 797 798 798 799 799 /* Enable/Disable SMART on device */ -
ataprint.cpp
diff --git a/ataprint.cpp b/ataprint.cpp index 335ef64..bcc435d 100644
a b static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh) 3128 3128 } 3129 3129 3130 3130 // Print SCT Error Recovery Control timers 3131 static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer )3131 static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default = false) 3132 3132 { 3133 const char* power_on_str = (power_on ? "Power-on " : ""); 3133 3134 json::ref jref = jglb["ata_sct_erc"]; 3134 jout("SCT Error Recovery Control%s: \n", (set ? " set to" : ""));3135 jout("SCT Error Recovery Control%s:%s\n", (set ? " set to" : ""), (mfg_default ? " default values." : "")); 3135 3136 3136 jref["read"]["enabled"] = !!read_timer; 3137 if (!read_timer) 3138 jout(" Read: Disabled\n"); 3139 else { 3140 jout(" Read: %6d (%0.1f seconds)\n", read_timer, read_timer/10.0); 3141 jref["read"]["deciseconds"] = read_timer; 3142 } 3137 if (!mfg_default) { 3138 jref["read"]["enabled"] = !!read_timer; 3139 if (!read_timer) 3140 jout(" %sRead: Disabled\n", power_on_str); 3141 else { 3142 jout(" %sRead: %6d (%0.1f seconds)\n", power_on_str, read_timer, read_timer/10.0); 3143 jref["read"]["deciseconds"] = read_timer; 3144 } 3143 3145 3144 jref["write"]["enabled"] = !!write_timer; 3145 if (!write_timer) 3146 jout(" Write: Disabled\n"); 3147 else { 3148 jout(" Write: %6d (%0.1f seconds)\n", write_timer, write_timer/10.0); 3149 jref["write"]["deciseconds"] = write_timer; 3146 jref["write"]["enabled"] = !!write_timer; 3147 if (!write_timer) 3148 jout(" %sWrite: Disabled\n", power_on_str); 3149 else { 3150 jout(" %sWrite: %6d (%0.1f seconds)\n", power_on_str, write_timer, write_timer/10.0); 3151 jref["write"]["deciseconds"] = write_timer; 3152 } 3150 3153 } 3151 3154 } 3152 3155 … … int ataPrintMain (ata_device * device, const ata_print_options & options) 4348 4351 bool sct_erc_get = options.sct_erc_get; 4349 4352 if (options.sct_erc_set) { 4350 4353 // Set SCT Error Recovery Control 4351 if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime )4352 || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime )) {4354 if ( ataSetSCTErrorRecoveryControltime(device, 1, options.sct_erc_readtime, options.sct_erc_power_on, options.sct_erc_mfg_default ) 4355 || ataSetSCTErrorRecoveryControltime(device, 2, options.sct_erc_writetime, options.sct_erc_power_on, options.sct_erc_mfg_default)) { 4353 4356 pout("SCT (Set) Error Recovery Control command failed\n"); 4354 4357 if (!( (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70) 4355 4358 || (options.sct_erc_readtime == 0 && options.sct_erc_writetime == 0))) … … int ataPrintMain (ata_device * device, const ata_print_options & options) 4359 4362 } 4360 4363 else if (!sct_erc_get) 4361 4364 ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, 4362 options.sct_erc_writetime );4365 options.sct_erc_writetime, options.sct_erc_power_on, options.sct_erc_mfg_default); 4363 4366 } 4364 4367 4365 4368 if (sct_erc_get) { 4366 4369 // Print SCT Error Recovery Control 4367 4370 unsigned short read_timer, write_timer; 4368 if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer )4369 || ataGetSCTErrorRecoveryControltime(device, 2, write_timer )) {4371 if ( ataGetSCTErrorRecoveryControltime(device, 1, read_timer, options.sct_erc_power_on ) 4372 || ataGetSCTErrorRecoveryControltime(device, 2, write_timer, options.sct_erc_power_on)) { 4370 4373 pout("SCT (Get) Error Recovery Control command failed\n"); 4371 4374 if (options.sct_erc_set) { 4372 4375 pout("The previous SCT (Set) Error Recovery Control command succeeded\n"); 4373 4376 ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime, 4374 options.sct_erc_writetime );4377 options.sct_erc_writetime, options.sct_erc_power_on); 4375 4378 } 4376 4379 failuretest(OPTIONAL_CMD, returnval|=FAILSMART); 4377 4380 } 4378 4381 else 4379 ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer );4382 ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer, options.sct_erc_power_on); 4380 4383 } 4381 4384 pout("\n"); 4382 4385 } -
ataprint.h
diff --git a/ataprint.h b/ataprint.h index 638db1e..2e007e4 100644
a b struct ata_print_options 58 58 bool sct_erc_get; 59 59 bool sct_erc_set; 60 60 unsigned sct_erc_readtime, sct_erc_writetime; 61 bool sct_erc_power_on; 62 bool sct_erc_mfg_default; 61 63 bool sataphy, sataphy_reset; 62 64 63 65 bool smart_disable, smart_enable; … … struct ata_print_options 125 127 sct_erc_get(false), 126 128 sct_erc_set(false), 127 129 sct_erc_readtime(0), sct_erc_writetime(0), 130 sct_erc_power_on(false), 131 sct_erc_mfg_default(false), 128 132 sataphy(false), sataphy_reset(false), 129 133 smart_disable(false), smart_enable(false), 130 134 smart_auto_offl_disable(false), smart_auto_offl_enable(false), -
smartctl.8.in
diff --git a/smartctl.8.in b/smartctl.8.in index dad017a..a511bc4 100644
a b Otherwise, the setting is volatile and will be reverted to the last 1491 1491 non-volatile setting by the next hard reset. The default interval 1492 1492 is vendor specific, typical values are 1, 2, or 5 minutes. 1493 1493 .Sp 1494 .I scterc[,READTIME,WRITETIME] 1494 .I scterc[,READTIME,WRITETIME][,p|r] 1495 1495 \- [ATA only] prints values and descriptions of the SCT Error Recovery 1496 1496 Control settings. 1497 1497 These are equivalent to TLER (as used by Western Digital), CCTL (as used … … READTIME and WRITETIME arguments (deciseconds) set the specified values. 1500 1500 Values of 0 disable the feature, other values less than 65 are probably not 1501 1501 supported. 1502 1502 For RAID configurations, this is typically set to 70,70 deciseconds. 1503 If \*(Aq,p\*(Aq is specified with read and write time values, these 1504 time values will be persistent over a power-on reset. If \*(Aq,p\*(Aq is 1505 specified without read and write time values, the persistent over power-on 1506 values will be returned. 1507 If \*(Aq,r\*(Aq is specified, all SCT timer settings are restored to the 1508 manufacturer's default value. 1509 The \*(Aq,p\*(Aq and \*(Aq,r\*(Aq options require the device to support ACS-4 1510 or higher. 1503 1511 .Sp 1504 1512 .I devstat[,PAGE] 1505 1513 \- [ATA only] prints values and descriptions of the ATA Device Statistics -
smartctl.cpp
diff --git a/smartctl.cpp b/smartctl.cpp index d4db32b..b0bf682 100644
a b static void Usage() 176 176 " Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" 177 177 " xerror[,N][,error], xselftest[,N][,selftest], background,\n" 178 178 " sasphy[,reset], sataphy[,reset], scttemp[sts,hist],\n" 179 " scttempint,N[,p], scterc[,N,M] , devstat[,N], defects[,N], ssd,\n"179 " scttempint,N[,p], scterc[,N,M][,p|r], devstat[,N], defects[,N], ssd,\n" 180 180 " gplog,N[,RANGE], smartlog,N[,RANGE], nvmelog,N,SIZE\n\n" 181 181 " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" 182 182 " Set display OPTION for vendor Attribute N (see man page)\n\n" … … static std::string getvalidarglist(int opt) 243 243 "xerror[,N][,error], xselftest[,N][,selftest], " 244 244 "background, sasphy[,reset], sataphy[,reset], " 245 245 "scttemp[sts,hist], scttempint,N[,p], " 246 "scterc[,N,M] , devstat[,N], defects[,N], ssd, "246 "scterc[,N,M][,p|r], devstat[,N], defects[,N], ssd, " 247 247 "gplog,N[,RANGE], smartlog,N[,RANGE], " 248 248 "nvmelog,N,SIZE"; 249 249 case 'P': … … static int parse_options(int argc, char** argv, const char * & type, 615 615 badarg = true; 616 616 617 617 } else if (!strncmp(optarg, "scterc,", sizeof("scterc,")-1)) { 618 unsigned rt = ~0, wt = ~0; int n = -1; 619 sscanf(optarg,"scterc,%u,%u%n", &rt, &wt, &n); 620 if (n == (int)strlen(optarg) && rt <= 999 && wt <= 999) { 618 ataopts.sct_erc_power_on = false; 619 ataopts.sct_erc_mfg_default = false; 620 unsigned rt = ~0, wt = ~0; char opt = 0; int n = -1; 621 sscanf(optarg,"scterc,%u,%u,%c%n", &rt, &wt, &opt, &n); 622 if (n == (int)strlen(optarg) && rt <= 999 && wt <= 999 && toupper(opt) == 'P') { 621 623 ataopts.sct_erc_set = true; 622 624 ataopts.sct_erc_readtime = rt; 623 625 ataopts.sct_erc_writetime = wt; 626 ataopts.sct_erc_power_on = true; 624 627 } 625 628 else { 626 snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); 627 badarg = true; 629 sscanf(optarg,"scterc,%u,%u%n", &rt, &wt, &n); 630 if (n == (int)strlen(optarg) && rt <= 999 && wt <= 999) { 631 ataopts.sct_erc_set = true; 632 ataopts.sct_erc_readtime = rt; 633 ataopts.sct_erc_writetime = wt; 634 } else { 635 sscanf(optarg,"scterc,%c%n", &opt, &n); 636 if (n == (int)strlen(optarg) && (toupper(opt) == 'P' || toupper(opt) == 'R')) { 637 if (toupper(opt) == 'R') { 638 ataopts.sct_erc_set = true; 639 ataopts.sct_erc_mfg_default = true; 640 } else { /* P */ 641 ataopts.sct_erc_get = true; 642 ataopts.sct_erc_power_on = true; 643 } 644 } else { 645 snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME][,P|R] syntax error\n"); 646 badarg = true; 647 } 648 } 628 649 } 629 650 } else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) 630 651 || !strncmp(optarg, "smartlog,", sizeof("smartlog,")-1)) { -
smartd.cpp
diff --git a/smartd.cpp b/smartd.cpp index c352dde..45b2fe9 100644
a b static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade 2313 2313 else if (locked) 2314 2314 PrintOut(LOG_INFO, "Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n", 2315 2315 name); 2316 else if ( ataSetSCTErrorRecoveryControltime(atadev, 1, cfg.sct_erc_readtime )2317 || ataSetSCTErrorRecoveryControltime(atadev, 2, cfg.sct_erc_writetime ))2316 else if ( ataSetSCTErrorRecoveryControltime(atadev, 1, cfg.sct_erc_readtime, false, false ) 2317 || ataSetSCTErrorRecoveryControltime(atadev, 2, cfg.sct_erc_writetime, false, false)) 2318 2318 PrintOut(LOG_INFO, "Device: %s, set of SCT Error Recovery Control failed\n", name); 2319 2319 else 2320 2320 PrintOut(LOG_INFO, "Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",