Ticket #723: 0001-Add-wcache-sct-option-for-g-s-to-control-wcache-in-S.patch

File 0001-Add-wcache-sct-option-for-g-s-to-control-wcache-in-S.patch, 14.2 KB (added by Song Liu, 8 years ago)

This patch was generated with git (git-svn). I am not sure whether it is ok.

  • trunk/smartmontools/atacmds.cpp

    From 22321ac3562706b859fd16b824ca1c73264a902b Mon Sep 17 00:00:00 2001
    From: Song Liu <songliubraving@fb.com>
    Date: Thu, 11 Aug 2016 09:00:44 -0700
    Subject: [PATCH] Add wcache-sct option for -g -s to control wcache in SCT
    MIME-Version: 1.0
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: 8bit
    
    The option is described as following in man page:
    
    wcache-sct[,ata|on|off[,p]]  -  [ATA only] Gets/sets the write
    cache feature through SCT Feature Control (if supported). The
    state of write cache in SCT Feature Control could be
    "Controlled by ATA", "Force Enabled", or "Force Disabled". SCT
    Feature control overwrites the setting by ATA Set Features
    command (wcache[,on|off] option).  If SCT Feature Control sets
    write cache as "Force Enabled" or "Force Disabled", the setting
    of wcache[,on|off] is ignored by the drive.  SCT  Feature Control
    usually sets write cache as "Controlled by ATA" by default.
    If ´,p´ is specified, the setting is preserved across power cycles.
    
    We reuse code for wcreorder, so there isn't much change in the
    backend. Persistent flag is added to trigger persistent flag in
    SCT command.
    ---
     trunk/smartmontools/atacmds.cpp   | 25 ++++++++++++++++-----
     trunk/smartmontools/atacmds.h     |  6 +++++
     trunk/smartmontools/ataprint.cpp  | 46 +++++++++++++++++++++++++++++++++++++-
     trunk/smartmontools/ataprint.h    |  7 +++++-
     trunk/smartmontools/smartctl.8.in | 10 +++++++++
     trunk/smartmontools/smartctl.cpp  | 47 ++++++++++++++++++++++++++++++++++-----
     6 files changed, 128 insertions(+), 13 deletions(-)
    
    diff --git a/trunk/smartmontools/atacmds.cpp b/trunk/smartmontools/atacmds.cpp
    index c470b1c..f2eb092 100644
    a b int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *  
    23072307  return 0;
    23082308}
    23092309
    2310 // Get/Set Write Cache Reordering
    2311 int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set)
     2310// Common function for Get/Set SCT Feature Control:
     2311// Write Cache, Write Cache Reordering, etc.
     2312static int ataGetSetSCTFeatureControl(ata_device * device, unsigned short feature_code,
     2313                                      unsigned short state, bool persistent, bool set)
    23122314{
    23132315  // Check initial status
    23142316  ata_sct_status_response sts;
    int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool pers  
    23272329  // CAUTION: DO NOT CHANGE THIS VALUE (SOME ACTION CODES MAY ERASE DISK)
    23282330  cmd.action_code   = 4; // Feature Control command
    23292331  cmd.function_code  = (set ? 1 : 2); // 1=Set, 2=Get
    2330   cmd.feature_code  = 2; //  Enable/Disable Write Cache Reordering
    2331   cmd.state         = (enable ? 1 : 2); // 1 enable, 2 disable
     2332  cmd.feature_code  = feature_code;
     2333  cmd.state         = state;
    23322334  cmd.option_flags  = (persistent ? 0x01 : 0x00);
    23332335
    23342336  // swap endian order if needed
    int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool pers  
    23592361      (!set ? 'G' : 'S'), device->get_errmsg());
    23602362    return -1;
    23612363  }
    2362   int state = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
     2364  state = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
    23632365
    23642366  // re-read and check SCT status
    23652367  if (ataReadSCTStatus(device, &sts))
    int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool pers  
    23732375  return state;
    23742376}
    23752377
     2378// Get/Set Write Cache Reordering
     2379int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set)
     2380{
     2381  return ataGetSetSCTFeatureControl(device, 2 /* Enable/Disable Write Cache Reordering */,
     2382                                    (enable ? 1 : 2), persistent, set);
     2383}
     2384
     2385// Get/Set Write Cache (force enable, force disable,
     2386int ataGetSetSCTWriteCache(ata_device * device, unsigned short state, bool persistent, bool set)
     2387{
     2388  return ataGetSetSCTFeatureControl(device, 1 /* Enable/Disable Write Cache */,
     2389                                    state, persistent, set);
     2390}
    23762391
    23772392// Set SCT Temperature Logging Interval
    23782393int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persistent)
  • trunk/smartmontools/atacmds.h

    diff --git a/trunk/smartmontools/atacmds.h b/trunk/smartmontools/atacmds.h
    index 4cd768a..d172a02 100644
    a b int ataSmartSupport(const ata_identify_device * drive);  
    845845int ataGetSetSCTWriteCacheReordering(ata_device * device, bool enable, bool persistent, bool set);
    846846
    847847// Return values:
     848// 1: Write cache controled by ATA Set Features command
     849// 2: Force enable write cache
     850// 3: Force disable write cache
     851int ataGetSetSCTWriteCache(ata_device * device, unsigned short state, bool persistent, bool set);
     852
     853// Return values:
    848854//  1: SMART enabled
    849855//  0: SMART disabled
    850856// -1: can't tell if SMART is enabled -- try issuing ataDoesSmartWork command to see
  • trunk/smartmontools/ataprint.cpp

    diff --git a/trunk/smartmontools/ataprint.cpp b/trunk/smartmontools/ataprint.cpp
    index 593e2cb..aa81cf0 100644
    a b int ataPrintMain (ata_device * device, const ata_print_options & options)  
    26382638       || options.sct_erc_set
    26392639       || options.sct_wcache_reorder_get
    26402640       || options.sct_wcache_reorder_set
     2641       || options.sct_wcache_sct_get
     2642       || options.sct_wcache_sct_set
    26412643  );
    26422644
    26432645  // Exit if no further options specified
    int ataPrintMain (ata_device * device, const ata_print_options & options)  
    28212823    }
    28222824  }
    28232825
     2826  const char * sct_write_cache_state_desc[4] = {
     2827    "Unknown",            // 0: not defined in standard but returned on some drives if not set
     2828    "Controlled by ATA",  // 1: controlled ATA Set Features command
     2829    "Force Enabled",      // 2
     2830    "Force Disabled"      // 3
     2831  };
     2832 
     2833  // Print SCT feature control of write cache
     2834  if (options.sct_wcache_sct_get) {
     2835    if (!isSCTFeatureControlCapable(&drive))
     2836      pout("SCT Write Cache Control: Unavailable\n");
     2837    else if (locked)
     2838      pout("SCT Write Cache Control: Unknown (SCT not supported if ATA Security is LOCKED)\n");
     2839    else {
     2840      int state = ataGetSetSCTWriteCache(device, 1, false /*persistent*/, false /*set*/);
     2841      if (-1 <= state && state <= 3)
     2842        pout("SCT Write Cache Control: %s\n",
     2843             (state == -1 ? "Unknown (SCT Feature Control command failed)" :
     2844              sct_write_cache_state_desc[state]));
     2845      else
     2846        pout("SCT Write Cache Control: Unknown (0x%02x)\n", state);
     2847    }
     2848  }
     2849
     2850
    28242851  // Print remaining drive info
    28252852  if (options.drive_info) {
    28262853    // Print the (now possibly changed) power mode if available
    int ataPrintMain (ata_device * device, const ata_print_options & options)  
    28392866      || options.smart_auto_offl_disable || options.smart_auto_offl_enable
    28402867      || options.set_aam || options.set_apm || options.set_lookahead
    28412868      || options.set_wcache || options.set_security_freeze || options.set_standby
    2842       || options.sct_wcache_reorder_set)
     2869      || options.sct_wcache_reorder_set || options.sct_wcache_sct_set)
    28432870    pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
    28442871 
    28452872  // Enable/Disable AAM
    int ataPrintMain (ata_device * device, const ata_print_options & options)  
    29222949      pout("Write cache reordering %sabled\n", (enable ? "en" : "dis"));
    29232950  }
    29242951
     2952  // Enable/Disable write cache in SCT
     2953  if (options.sct_wcache_sct_set) {
     2954    if (!isSCTFeatureControlCapable(&drive))
     2955      pout("SCT Feature Control of write cache failed: SCT Feature Control command not supported\n");
     2956    else if (locked)
     2957      pout("SCT Feature Control of write cache failed: SCT not supported if ATA Security is LOCKED\n");
     2958    else if (ataGetSetSCTWriteCache(device,
     2959               options.sct_wcache_sct_set, options.sct_wcache_sct_set_pers, true /*set*/) < 0) {
     2960      pout("SCT Feature Control of write cache failed: %s\n", device->get_errmsg());
     2961      returnval |= FAILSMART;
     2962    }
     2963    else
     2964      pout("Write cache SCT Feature Control is set to: %s (%s)\n",
     2965           sct_write_cache_state_desc[options.sct_wcache_sct_set],
     2966           (options.sct_wcache_sct_set_pers ? "persistent" : "volatile"));
     2967  }
     2968
    29252969  // Freeze ATA security
    29262970  if (options.set_security_freeze) {
    29272971    if (!ata_nodata_command(device, ATA_SECURITY_FREEZE_LOCK)) {
  • trunk/smartmontools/ataprint.h

    diff --git a/trunk/smartmontools/ataprint.h b/trunk/smartmontools/ataprint.h
    index 74e28b9..230ce22 100644
    a b struct ata_print_options  
    108108  int set_wcache; // disable(-1), enable(1) write cache
    109109  bool sct_wcache_reorder_get; // print write cache reordering status
    110110  int sct_wcache_reorder_set; // disable(-1), enable(1) write cache reordering
     111  bool sct_wcache_sct_get; // print SCT Feature Control of write cache status
     112  int sct_wcache_sct_set; // determined by ata set features command(1), force enable(2), force disable(3)
     113  bool sct_wcache_sct_set_pers; // persistent or volatile
    111114
    112115  ata_print_options()
    113116    : drive_info(false),
    struct ata_print_options  
    145148      set_standby(0), set_standby_now(false),
    146149      get_security(false), set_security_freeze(false),
    147150      get_wcache(false), set_wcache(0),
    148       sct_wcache_reorder_get(false), sct_wcache_reorder_set(0)
     151      sct_wcache_reorder_get(false), sct_wcache_reorder_set(0),
     152      sct_wcache_sct_get(false), sct_wcache_sct_set(0),
     153      sct_wcache_sct_set_pers(false)
    149154    { }
    150155};
    151156
  • trunk/smartmontools/smartctl.8.in

    diff --git a/trunk/smartmontools/smartctl.8.in b/trunk/smartmontools/smartctl.8.in
    index 765e8d3..372f331 100644
    a b The write cache is usually enabled by default.  
    947947\- [SCSI] Gets/sets the \'Write Cache Enable\' (WCE) bit (if supported).
    948948The write cache is usually enabled by default.
    949949
     950.I wcache-sct[,ata|on|off[,p]]
     951\- [ATA only] Gets/sets the write cache feature through SCT Feature Control
     952(if supported). The state of write cache in SCT Feature Control could be
     953"Controlled by ATA", "Force Enabled", or "Force Disabled". SCT Feature control
     954overwrites the setting by ATA Set Features command (wcache[,on|off] option).
     955If SCT Feature Control sets write cache as "Force Enabled" or "Force Disabled",
     956the setting of wcache[,on|off] is ignored by the drive. SCT Feature Control
     957usually sets write cache as "Controlled by ATA" by default. If ´,p´ is
     958specified, the setting is preserved across power cycles.
     959
    950960.I wcreorder[,on|off]
    951961\- [ATA only] Gets/sets Write Cache Reordering.
    952962If it is disabled (off), disk write scheduling is executed on a
  • trunk/smartmontools/smartctl.cpp

    diff --git a/trunk/smartmontools/smartctl.cpp b/trunk/smartmontools/smartctl.cpp
    index aee253c..7660b9c 100644
    a b static void Usage()  
    8787"  --identify[=[w][nvb]]\n"
    8888"         Show words and bits from IDENTIFY DEVICE data                (ATA)\n\n"
    8989"  -g NAME, --get=NAME\n"
    90 "        Get device setting: all, aam, apm, lookahead, security, wcache, rcache, wcreorder\n\n"
     90"        Get device setting: all, aam, apm, lookahead, security, wcache, rcache, wcreorder, wcache-sct\n\n"
    9191"  -a, --all\n"
    9292"         Show all SMART information for device\n\n"
    9393"  -x, --xall\n"
    static void Usage()  
    123123"  -s NAME[,VALUE], --set=NAME[,VALUE]\n"
    124124"        Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n"
    125125"        lookahead,[on|off], security-freeze, standby,[N|off|now],\n"
    126 "        wcache,[on|off], rcache,[on|off], wcreorder,[on|off]\n\n"
     126"        wcache,[on|off], rcache,[on|off], wcreorder,[on|off]\n"
     127"        wcache-sct,[ata|on|off[,p]]\n\n"
    127128  );
    128129  printf(
    129130"======================================= READ AND DISPLAY DATA OPTIONS =====\n\n"
    static std::string getvalidarglist(int opt)  
    221222  case 'f':
    222223    return "old, brief, hex[,id|val]";
    223224  case 'g':
    224     return "aam, apm, lookahead, security, wcache, rcache, wcreorder";
     225    return "aam, apm, lookahead, security, wcache, rcache, wcreorder, wcache-sct";
    225226  case opt_set:
    226227    return "aam,[N|off], apm,[N|off], lookahead,[on|off], security-freeze, "
    227            "standby,[N|off|now], wcache,[on|off], rcache,[on|off], wcreorder,[on|off]";
     228           "standby,[N|off|now], wcache,[on|off], rcache,[on|off], wcreorder,[on|off], "
     229           "wcache-sct,[ata|on|off[,p]]";
    228230  case 's':
    229231    return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set);
    230232  case opt_identify:
    static const char * parse_options(int argc, char** argv,  
    854856        bool get = (optchar == 'g');
    855857        char name[16+1]; unsigned val;
    856858        int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg);
     859        bool persistent = false;
    857860        if (sscanf(optarg, "%16[^,=]%n%*[,=]%n%u%n", name, &n1, &n2, &val, &n3) >= 1
    858861            && (n1 == len || (!get && n2 > 0))) {
    859           bool on  = (n2 > 0 && !strcmp(optarg+n2, "on"));
    860           bool off = (n2 > 0 && !strcmp(optarg+n2, "off"));
     862          bool on  = false;
     863          bool off = false;
     864          bool ata = false;
     865
     866          if (n2 > 0) {
     867            int len2 = strlen(optarg + n2);
     868            char * tmp = strstr(optarg+n2, ",p");
     869            // handle ",p" in persistent options like: wcache-sct,[ata|on|off],p
     870            if (tmp && (strlen(tmp) == 2)) {
     871              persistent = true;
     872              len2 = strlen(optarg+n2) - 2;
     873
     874              // the ,p option only works for set of SCT Feature Control command
     875              if (strcmp(name, "wcache-sct") != 0)
     876                badarg = true;
     877            }
     878            on  = !strncmp(optarg+n2, "on", len2);
     879            off = !strncmp(optarg+n2, "off", len2);
     880            ata = !strncmp(optarg+n2, "ata", len2);
     881          }
    861882          if (n3 != len)
    862883            val = ~0U;
    863884
    static const char * parse_options(int argc, char** argv,  
    913934            else
    914935              badarg = true;
    915936          }
     937          else if (!strcmp(name, "wcache-sct")) {
     938            ataopts.sct_wcache_sct_set_pers = persistent;
     939            if (get) {
     940              ataopts.sct_wcache_sct_get = true;
     941            }
     942            else if (off)
     943              ataopts.sct_wcache_sct_set = 3;
     944            else if (on)
     945              ataopts.sct_wcache_sct_set = 2;
     946            else if (ata)
     947              ataopts.sct_wcache_sct_set = 1;
     948            else
     949              badarg = true;
     950          }
    916951          else if (!strcmp(name, "rcache")) {
    917952            if (get)
    918953              scsiopts.get_rcd = true;