Ticket #1427: acs4_sct_ert_enhancements_v0.patch

File acs4_sct_ert_enhancements_v0.patch, 14.9 KB (added by Jeremy Bauer, 3 months ago)

Git patch file for ACS-4 scterc improvements

  • 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 
    24142414
    24152415// Get/Set SCT Error Recovery Control
    24162416static 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)
    24182419{
    24192420  // Check initial status
    24202421  ata_sct_status_response sts;
    static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 
    24322433  ata_sct_error_recovery_control_command cmd; memset(&cmd, 0, sizeof(cmd));
    24332434  // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
    24342435  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
    24362447  cmd.selection_code = type; // 1=Read timer, 2=Write timer
    24372448  if (set)
    24382449    cmd.time_limit   = time_limit;
    static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 
    24692480  if (ataReadSCTStatus(device, &sts))
    24702481    return -1;
    24712482
    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)) {
    24732484    pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
    24742485      sts.ext_status_code, sts.action_code, sts.function_code);
    24752486    return -1;
    static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty 
    24982509}
    24992510
    25002511// Get SCT Error Recovery Control
    2501 int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit)
     2512int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on)
    25022513{
    2503   return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit);
     2514  return ataGetSetSCTErrorRecoveryControltime(device, type, false/*get*/, time_limit, power_on, false);
    25042515}
    25052516
    25062517// Set SCT Error Recovery Control
    2507 int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit)
     2518int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit,
     2519                                      bool power_on, bool mfg_default)
    25082520{
    2509   return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit);
     2521  return ataGetSetSCTErrorRecoveryControltime(device, type, true/*set*/, time_limit, power_on, mfg_default);
    25102522}
    25112523
    25122524
  • atacmds.h

    diff --git a/atacmds.h b/atacmds.h
    index 94c9ae9..9e81377 100644
    a b STATIC_ASSERT(sizeof(ata_sct_status_response) == 512); 
    545545struct ata_sct_error_recovery_control_command
    546546{
    547547  unsigned short action_code;       // 3 = Error Recovery Control
    548   unsigned short function_code;     // 1 = Set, 2 = Return
     548  unsigned short function_code;     // 1 = Set Current, 2 = Return Current, 3 = Set Power-on, 4 = Return Power-on, 5 = Restore Default
    549549  unsigned short selection_code;    // 1 = Read Timer, 2 = Write Timer
    550550  unsigned short time_limit;        // If set: Recovery time limit in 100ms units
    551551  unsigned short words004_255[252]; // reserved
    int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table * 
    792792int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent);
    793793
    794794// 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);
     795int ataGetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short & time_limit, bool power_on);
     796int ataSetSCTErrorRecoveryControltime(ata_device * device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default);
    797797
    798798
    799799/* 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) 
    31283128}
    31293129
    31303130// Print SCT Error Recovery Control timers
    3131 static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer)
     3131static void ataPrintSCTErrorRecoveryControl(bool set, unsigned short read_timer, unsigned short write_timer, bool power_on, bool mfg_default = false)
    31323132{
     3133  const char* power_on_str = (power_on ? "Power-on " : "");
    31333134  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." : ""));
    31353136
    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    }
    31433145
    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    }
    31503153  }
    31513154}
    31523155
    int ataPrintMain (ata_device * device, const ata_print_options & options) 
    43484351      bool sct_erc_get = options.sct_erc_get;
    43494352      if (options.sct_erc_set) {
    43504353        // 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)) {
    43534356          pout("SCT (Set) Error Recovery Control command failed\n");
    43544357          if (!(   (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70)
    43554358                || (options.sct_erc_readtime ==  0 && options.sct_erc_writetime ==  0)))
    int ataPrintMain (ata_device * device, const ata_print_options & options) 
    43594362        }
    43604363        else if (!sct_erc_get)
    43614364          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);
    43634366      }
    43644367
    43654368      if (sct_erc_get) {
    43664369        // Print SCT Error Recovery Control
    43674370        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)) {
    43704373          pout("SCT (Get) Error Recovery Control command failed\n");
    43714374          if (options.sct_erc_set) {
    43724375            pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
    43734376            ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime,
    4374               options.sct_erc_writetime);
     4377              options.sct_erc_writetime, options.sct_erc_power_on);
    43754378          }
    43764379          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
    43774380        }
    43784381        else
    4379           ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer);
     4382          ataPrintSCTErrorRecoveryControl(false, read_timer, write_timer, options.sct_erc_power_on);
    43804383      }
    43814384      pout("\n");
    43824385    }
  • ataprint.h

    diff --git a/ataprint.h b/ataprint.h
    index 638db1e..2e007e4 100644
    a b struct ata_print_options 
    5858  bool sct_erc_get;
    5959  bool sct_erc_set;
    6060  unsigned sct_erc_readtime, sct_erc_writetime;
     61  bool sct_erc_power_on;
     62  bool sct_erc_mfg_default;
    6163  bool sataphy, sataphy_reset;
    6264
    6365  bool smart_disable, smart_enable;
    struct ata_print_options 
    125127      sct_erc_get(false),
    126128      sct_erc_set(false),
    127129      sct_erc_readtime(0), sct_erc_writetime(0),
     130      sct_erc_power_on(false),
     131      sct_erc_mfg_default(false),
    128132      sataphy(false), sataphy_reset(false),
    129133      smart_disable(false), smart_enable(false),
    130134      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 
    14911491non-volatile setting by the next hard reset.  The default interval
    14921492is vendor specific, typical values are 1, 2, or 5 minutes.
    14931493.Sp
    1494 .I scterc[,READTIME,WRITETIME]
     1494.I scterc[,READTIME,WRITETIME][,p|r]
    14951495\- [ATA only] prints values and descriptions of the SCT Error Recovery
    14961496Control settings.
    14971497These are equivalent to TLER (as used by Western Digital), CCTL (as used
    READTIME and WRITETIME arguments (deciseconds) set the specified values. 
    15001500Values of 0 disable the feature, other values less than 65 are probably not
    15011501supported.
    15021502For RAID configurations, this is typically set to 70,70 deciseconds.
     1503If \*(Aq,p\*(Aq is specified with read and write time values, these
     1504time values will be persistent over a power-on reset.  If \*(Aq,p\*(Aq is
     1505specified without read and write time values, the persistent over power-on
     1506values will be returned.
     1507If \*(Aq,r\*(Aq is specified, all SCT timer settings are restored to the
     1508manufacturer's default value.
     1509The \*(Aq,p\*(Aq and \*(Aq,r\*(Aq options require the device to support ACS-4
     1510or higher.
    15031511.Sp
    15041512.I devstat[,PAGE]
    15051513\- [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() 
    176176"        Show device log. TYPE: error, selftest, selective, directory[,g|s],\n"
    177177"        xerror[,N][,error], xselftest[,N][,selftest], background,\n"
    178178"        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"
    180180"        gplog,N[,RANGE], smartlog,N[,RANGE], nvmelog,N,SIZE\n\n"
    181181"  -v N,OPTION , --vendorattribute=N,OPTION                            (ATA)\n"
    182182"        Set display OPTION for vendor Attribute N (see man page)\n\n"
    static std::string getvalidarglist(int opt) 
    243243           "xerror[,N][,error], xselftest[,N][,selftest], "
    244244           "background, sasphy[,reset], sataphy[,reset], "
    245245           "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, "
    247247           "gplog,N[,RANGE], smartlog,N[,RANGE], "
    248248           "nvmelog,N,SIZE";
    249249  case 'P':
    static int parse_options(int argc, char** argv, const char * & type, 
    615615          badarg = true;
    616616
    617617      } 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') {
    621623          ataopts.sct_erc_set = true;
    622624          ataopts.sct_erc_readtime = rt;
    623625          ataopts.sct_erc_writetime = wt;
     626          ataopts.sct_erc_power_on = true;
    624627        }
    625628        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          }
    628649        }
    629650      } else if (   !strncmp(optarg, "gplog,"   , sizeof("gplog,"   )-1)
    630651                 || !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 
    23132313    else if (locked)
    23142314      PrintOut(LOG_INFO, "Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
    23152315               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))
    23182318      PrintOut(LOG_INFO, "Device: %s, set of SCT Error Recovery Control failed\n", name);
    23192319    else
    23202320      PrintOut(LOG_INFO, "Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",