From 4ac0377c20289d5b2b73d69d39d725874e17b651 Mon Sep 17 00:00:00 2001
From: Jonghwan Choi <jhbird.choi@gmail.com>
Date: Tue, 7 Mar 2017 14:31:02 +0900
Subject: [PATCH] smartcl: Add options '-g/s dsn' to get/set DSN feature
Signed-off-by: Jonghwan Choi <jhbird.choi@gmail.com>
---
atacmds.h | 1 +
ataprint.cpp | 27 +++++++++++++++++++++++++--
ataprint.h | 5 ++++-
smartctl.8.in | 4 ++++
smartctl.cpp | 23 ++++++++++++++++++-----
smartd.conf.5.in | 3 +++
smartd.cpp | 21 +++++++++++++++++----
7 files changed, 72 insertions(+), 12 deletions(-)
diff --git a/atacmds.h b/atacmds.h
index 7a32676..23b62cf 100644
|
a
|
b
|
typedef enum {
|
| 88 | 88 | #define ATA_ENABLE_APM 0x05 |
| 89 | 89 | #define ATA_ENABLE_WRITE_CACHE 0x02 |
| 90 | 90 | #define ATA_ENABLE_READ_LOOK_AHEAD 0xaa |
| | 91 | #define ATA_ENABLE_DISABLE_DSN 0x63 |
| 91 | 92 | |
| 92 | 93 | // 48-bit commands |
| 93 | 94 | #define ATA_READ_LOG_EXT 0x2F |
diff --git a/ataprint.cpp b/ataprint.cpp
index 9e9cbbb..daebc93 100644
|
a
|
b
|
int ataPrintMain (ata_device * device, const ata_print_options & options)
|
| 2795 | 2795 | !(drive.cfs_enable_1 & 0x0020) ? "Disabled" : "Enabled"); // word085 |
| 2796 | 2796 | } |
| 2797 | 2797 | |
| | 2798 | // Print DSN status |
| | 2799 | unsigned short word120 = drive.words088_255[120-88]; |
| | 2800 | if (options.get_dsn) { |
| | 2801 | if (!(drive.word086 & 0x8000) // word086 |
| | 2802 | || ((word120 & 0xc000) != 0x4000)) // word120 |
| | 2803 | pout("DSN feature is: Unavailable\n"); |
| | 2804 | else if (word120 & 0x200) // word120 |
| | 2805 | pout("DSN feature is: Enabled\n"); |
| | 2806 | else |
| | 2807 | pout("DSN feature is: Disabled\n"); |
| | 2808 | } |
| | 2809 | |
| 2798 | 2810 | // Check for ATA Security LOCK |
| 2799 | 2811 | unsigned short word128 = drive.words088_255[128-88]; |
| 2800 | 2812 | bool locked = ((word128 & 0x0007) == 0x0007); // LOCKED|ENABLED|SUPPORTED |
| … |
… |
int ataPrintMain (ata_device * device, const ata_print_options & options)
|
| 2866 | 2878 | || options.smart_auto_offl_disable || options.smart_auto_offl_enable |
| 2867 | 2879 | || options.set_aam || options.set_apm || options.set_lookahead |
| 2868 | 2880 | || options.set_wcache || options.set_security_freeze || options.set_standby |
| 2869 | | || options.sct_wcache_reorder_set || options.sct_wcache_sct_set) |
| | 2881 | || options.sct_wcache_reorder_set || options.sct_wcache_sct_set || options.set_dsn) |
| 2870 | 2882 | pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); |
| 2871 | 2883 | |
| 2872 | 2884 | // Enable/Disable AAM |
| … |
… |
int ataPrintMain (ata_device * device, const ata_print_options & options)
|
| 2931 | 2943 | pout("Write cache %sabled\n", (enable ? "en" : "dis")); |
| 2932 | 2944 | } |
| 2933 | 2945 | |
| | 2946 | // Enable/Disable DSN |
| | 2947 | if (options.set_dsn) { |
| | 2948 | bool enable = (options.set_dsn > 0); |
| | 2949 | if (!ata_set_features(device, ATA_ENABLE_DISABLE_DSN, (enable ? 0x1 : 0x2))) { |
| | 2950 | pout("DSN %sable failed: %s\n", (enable ? "en" : "dis"), device->get_errmsg()); |
| | 2951 | returnval |= FAILSMART; |
| | 2952 | } |
| | 2953 | else |
| | 2954 | pout("DSN %sabled\n", (enable ? "en" : "dis")); |
| | 2955 | } |
| | 2956 | |
| 2934 | 2957 | // Enable/Disable write cache reordering |
| 2935 | 2958 | if (options.sct_wcache_reorder_set) { |
| 2936 | 2959 | bool enable = (options.sct_wcache_reorder_set > 0); |
| … |
… |
int ataPrintMain (ata_device * device, const ata_print_options & options)
|
| 3100 | 3123 | || options.smart_auto_offl_disable || options.smart_auto_offl_enable |
| 3101 | 3124 | || options.set_aam || options.set_apm || options.set_lookahead |
| 3102 | 3125 | || options.set_wcache || options.set_security_freeze || options.set_standby |
| 3103 | | || options.sct_wcache_reorder_set) |
| | 3126 | || options.sct_wcache_reorder_set || options.set_dsn) |
| 3104 | 3127 | pout("\n"); |
| 3105 | 3128 | |
| 3106 | 3129 | // START OF READ-ONLY OPTIONS APART FROM -V and -i |
diff --git a/ataprint.h b/ataprint.h
index 1da201c..b8ccf1f 100644
|
a
|
b
|
struct ata_print_options
|
| 113 | 113 | bool sct_wcache_sct_get; // print SCT Feature Control of write cache status |
| 114 | 114 | int sct_wcache_sct_set; // determined by ata set features command(1), force enable(2), force disable(3) |
| 115 | 115 | bool sct_wcache_sct_set_pers; // persistent or volatile |
| | 116 | bool get_dsn; // print DSN status |
| | 117 | int set_dsn; // disable(02h), enable(01h) DSN |
| 116 | 118 | |
| 117 | 119 | ata_print_options() |
| 118 | 120 | : drive_info(false), |
| … |
… |
struct ata_print_options
|
| 153 | 155 | sct_wcache_reorder_get(false), sct_wcache_reorder_set(0), |
| 154 | 156 | sct_wcache_reorder_set_pers(false), |
| 155 | 157 | sct_wcache_sct_get(false), sct_wcache_sct_set(0), |
| 156 | | sct_wcache_sct_set_pers(false) |
| | 158 | sct_wcache_sct_set_pers(false), |
| | 159 | get_dsn(false), set_dsn(0) |
| 157 | 160 | { } |
| 158 | 161 | }; |
| 159 | 162 | |
diff --git a/smartctl.8.in b/smartctl.8.in
index df69e72..d55b21c 100644
|
a
|
b
|
commands. If ´,p´ is specified, the setting is preserved across power cycles.
|
| 1005 | 1005 | \'Off\' value disables read cache (if supported). |
| 1006 | 1006 | The read cache is usually enabled by default. |
| 1007 | 1007 | |
| | 1008 | .I dsn[,on|off] |
| | 1009 | \- [ATA only] Gets/sets the DSN feature (if supported). |
| | 1010 | The dsn is usually disabled by default. |
| | 1011 | |
| 1008 | 1012 | .TP |
| 1009 | 1013 | .B SMART READ AND DISPLAY DATA OPTIONS: |
| 1010 | 1014 | .TP |
diff --git a/smartctl.cpp b/smartctl.cpp
index 233220a..d05b2b3 100644
|
a
|
b
|
static void Usage()
|
| 87 | 87 | " --identify[=[w][nvb]]\n" |
| 88 | 88 | " Show words and bits from IDENTIFY DEVICE data (ATA)\n\n" |
| 89 | 89 | " -g NAME, --get=NAME\n" |
| 90 | | " Get device setting: all, aam, apm, lookahead, security, wcache, rcache, wcreorder, wcache-sct\n\n" |
| | 90 | " Get device setting: all, aam, apm, dsn, lookahead, security, wcache, rcache, wcreorder, wcache-sct\n\n" |
| 91 | 91 | " -a, --all\n" |
| 92 | 92 | " Show all SMART information for device\n\n" |
| 93 | 93 | " -x, --xall\n" |
| … |
… |
static void Usage()
|
| 122 | 122 | " Enable/disable Attribute autosave on device (on/off)\n\n" |
| 123 | 123 | " -s NAME[,VALUE], --set=NAME[,VALUE]\n" |
| 124 | 124 | " Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n" |
| 125 | | " lookahead,[on|off], security-freeze, standby,[N|off|now],\n" |
| | 125 | " dsn,[on|off], lookahead,[on|off], security-freeze, standby,[N|off|now],\n" |
| 126 | 126 | " wcache,[on|off], rcache,[on|off], wcreorder,[on|off[,p]]\n" |
| 127 | 127 | " wcache-sct,[ata|on|off[,p]]\n\n" |
| 128 | 128 | ); |
| … |
… |
static std::string getvalidarglist(int opt)
|
| 224 | 224 | case 'f': |
| 225 | 225 | return "old, brief, hex[,id|val]"; |
| 226 | 226 | case 'g': |
| 227 | | return "aam, apm, lookahead, security, wcache, rcache, wcreorder, wcache-sct"; |
| | 227 | return "aam, apm, dsn, lookahead, security, wcache, rcache, wcreorder, wcache-sct"; |
| 228 | 228 | case opt_set: |
| 229 | | return "aam,[N|off], apm,[N|off], lookahead,[on|off], security-freeze, " |
| | 229 | return "aam,[N|off], apm,[N|off], dsn,[on|off], lookahead,[on|off], security-freeze, " |
| 230 | 230 | "standby,[N|off|now], wcache,[on|off], rcache,[on|off], wcreorder,[on|off[,p]], " |
| 231 | 231 | "wcache-sct,[ata|on|off[,p]]"; |
| 232 | 232 | case 's': |
| … |
… |
static const char * parse_options(int argc, char** argv,
|
| 897 | 897 | if (get && !strcmp(name, "all")) { |
| 898 | 898 | ataopts.get_aam = ataopts.get_apm = true; |
| 899 | 899 | ataopts.get_security = true; |
| 900 | | ataopts.get_lookahead = ataopts.get_wcache = true; |
| | 900 | ataopts.get_lookahead = ataopts.get_wcache = ataopts.get_dsn = true; |
| 901 | 901 | scsiopts.get_rcd = scsiopts.get_wce = true; |
| 902 | 902 | } |
| 903 | 903 | else if (!strcmp(name, "aam")) { |
| … |
… |
static const char * parse_options(int argc, char** argv,
|
| 1006 | 1006 | else |
| 1007 | 1007 | badarg = true; |
| 1008 | 1008 | } |
| | 1009 | else if (!strcmp(name, "dsn")) { |
| | 1010 | if (get) { |
| | 1011 | ataopts.get_dsn = true; |
| | 1012 | } |
| | 1013 | else if (off) { |
| | 1014 | ataopts.set_dsn = -1; |
| | 1015 | } |
| | 1016 | else if (on) { |
| | 1017 | ataopts.set_dsn = 1; |
| | 1018 | } |
| | 1019 | else |
| | 1020 | badarg = true; |
| | 1021 | } |
| 1009 | 1022 | else |
| 1010 | 1023 | badarg = true; |
| 1011 | 1024 | } |
diff --git a/smartd.conf.5.in b/smartd.conf.5.in
index 95e35cf..be57541 100644
|
a
|
b
|
IDLE mode.
|
| 742 | 742 | |
| 743 | 743 | .I wcache,[on|off] |
| 744 | 744 | \- [ATA only] Sets the volatile write cache feature. |
| | 745 | |
| | 746 | .I dsn,[on|off] |
| | 747 | \- [ATA only] Sets the DSN feature. |
| 745 | 748 | .TP |
| 746 | 749 | .B \-s REGEXP |
| 747 | 750 | Run Self-Tests or Offline Immediate Tests, at scheduled times. A |
diff --git a/smartd.cpp b/smartd.cpp
index 8385cde..04dabdc 100644
|
a
|
b
|
struct dev_config
|
| 281 | 281 | int set_standby; // set(1..255->0..254) standby timer |
| 282 | 282 | bool set_security_freeze; // Freeze ATA security |
| 283 | 283 | int set_wcache; // disable(-1), enable(1) write cache |
| | 284 | int set_dsn; // disable(0x2), enable(0x1) DSN |
| 284 | 285 | |
| 285 | 286 | bool sct_erc_set; // set SCT ERC to: |
| 286 | 287 | unsigned short sct_erc_readtime; // ERC read time (deciseconds) |
| … |
… |
dev_config::dev_config()
|
| 328 | 329 | set_lookahead(0), |
| 329 | 330 | set_standby(0), |
| 330 | 331 | set_security_freeze(false), |
| 331 | | set_wcache(0), |
| | 332 | set_wcache(0), set_dsn(0), |
| 332 | 333 | sct_erc_set(false), |
| 333 | 334 | sct_erc_readtime(0), sct_erc_writetime(0), |
| 334 | 335 | curr_pending_id(0), offl_pending_id(0), |
| … |
… |
static void Directives()
|
| 1438 | 1439 | " -l TYPE Monitor SMART log or self-test status:\n" |
| 1439 | 1440 | " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n" |
| 1440 | 1441 | " -l scterc,R,W Set SCT Error Recovery Control\n" |
| 1441 | | " -e Change device setting: aam,[N|off], apm,[N|off], lookahead,[on|off],\n" |
| 1442 | | " security-freeze, standby,[N|off], wcache,[on|off]\n" |
| | 1442 | " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n" |
| | 1443 | " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n" |
| 1443 | 1444 | " -f Monitor 'Usage' Attributes, report failures\n" |
| 1444 | 1445 | " -m ADD Send email warning to address ADD\n" |
| 1445 | 1446 | " -M TYPE Modify email warning behavior (see man page)\n" |
| … |
… |
static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
|
| 2114 | 2115 | format_set_result_msg(msg, "Wr-cache", ata_set_features(atadev, |
| 2115 | 2116 | (cfg.set_wcache > 0? ATA_ENABLE_WRITE_CACHE : ATA_DISABLE_WRITE_CACHE)), cfg.set_wcache); |
| 2116 | 2117 | |
| | 2118 | if (cfg.set_dsn) |
| | 2119 | format_set_result_msg(msg, "DSN", ata_set_features(atadev, |
| | 2120 | ATA_ENABLE_DISABLE_DSN, (cfg.set_dsn > 0 ? 0x1 : 0x2))); |
| | 2121 | |
| 2117 | 2122 | if (cfg.set_security_freeze) |
| 2118 | 2123 | format_set_result_msg(msg, "Security freeze", |
| 2119 | 2124 | ata_nodata_command(atadev, ATA_SECURITY_FREEZE_LOCK)); |
| … |
… |
static void printoutvaliddirectiveargs(int priority, char d)
|
| 3843 | 3848 | PrintOut(priority, "%s", get_valid_firmwarebug_args()); |
| 3844 | 3849 | break; |
| 3845 | 3850 | case 'e': |
| 3846 | | PrintOut(priority, "aam,[N|off], apm,[N|off], lookahead,[on|off], " |
| | 3851 | PrintOut(priority, "aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] " |
| 3847 | 3852 | "security-freeze, standby,[N|off], wcache,[on|off]"); |
| 3848 | 3853 | break; |
| 3849 | 3854 | } |
| … |
… |
static int ParseToken(char * token, dev_config & cfg, smart_devtype_list & scan_
|
| 4365 | 4370 | else |
| 4366 | 4371 | badarg = true; |
| 4367 | 4372 | } |
| | 4373 | else if (!strcmp(arg2, "dsn")) { |
| | 4374 | if (off) |
| | 4375 | cfg.set_dsn = -1; |
| | 4376 | else if (on) |
| | 4377 | cfg.set_dsn = 1; |
| | 4378 | else |
| | 4379 | badarg = true; |
| | 4380 | } |
| 4368 | 4381 | else |
| 4369 | 4382 | badarg = true; |
| 4370 | 4383 | } |