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 | } |