Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sbin/atactl "smart status" already obtains the ata parameter...



details:   https://anonhg.NetBSD.org/src/rev/21d10878e81a
branches:  trunk
changeset: 446435:21d10878e81a
user:      mrg <mrg%NetBSD.org@localhost>
date:      Wed Dec 05 06:49:54 2018 +0000

description:
"smart status" already obtains the ata parameters to check if smart
is actually supported, so we can attempt to guess a vendor smart
table from the model name.  add basic support for all the micron /
crucial disk names i could find, and add a couple more micron
specific values.

XXX: probably should add regex support for matching, and probably
     should be more restrictive with the current matches.

diffstat:

 sbin/atactl/atactl.8 |   10 +++-
 sbin/atactl/atactl.c |  129 +++++++++++++++++++++++++++++++++++---------------
 2 files changed, 99 insertions(+), 40 deletions(-)

diffs (truncated from 312 to 300 lines):

diff -r 93cd6a57312f -r 21d10878e81a sbin/atactl/atactl.8
--- a/sbin/atactl/atactl.8      Wed Dec 05 05:52:23 2018 +0000
+++ b/sbin/atactl/atactl.8      Wed Dec 05 06:49:54 2018 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: atactl.8,v 1.26 2018/11/03 10:51:14 wiz Exp $
+.\"    $NetBSD: atactl.8,v 1.27 2018/12/05 06:49:54 mrg Exp $
 .\"
 .\" Copyright (c) 1998 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd October 4, 2018
+.Dd December 5, 2018
 .Dt ATACTL 8
 .Os
 .Sh NAME
@@ -162,6 +162,8 @@
 Currently, only
 .Dq micron
 has a vendor-specific table.
+If the vendor is not supplied, it may be guessed from devices' model
+or other data available.
 .It Ar offline #
 Runs the numbered offline self-test on the drive.
 .It Ar error-log
@@ -273,6 +275,10 @@
 .Xr scsictl 8
 command written by
 .An Jason R. Thorpe .
+.An Matthew R. Green
+significantly enhanced the 
+.Cm smart status
+support.
 .Sh BUGS
 The output from the
 .Cm identify
diff -r 93cd6a57312f -r 21d10878e81a sbin/atactl/atactl.c
--- a/sbin/atactl/atactl.c      Wed Dec 05 05:52:23 2018 +0000
+++ b/sbin/atactl/atactl.c      Wed Dec 05 06:49:54 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: atactl.c,v 1.78 2018/10/31 20:00:56 mrg Exp $  */
+/*     $NetBSD: atactl.c,v 1.79 2018/12/05 06:49:54 mrg Exp $  */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 #include <sys/cdefs.h>
 
 #ifndef lint
-__RCSID("$NetBSD: atactl.c,v 1.78 2018/10/31 20:00:56 mrg Exp $");
+__RCSID("$NetBSD: atactl.c,v 1.79 2018/12/05 06:49:54 mrg Exp $");
 #endif
 
 
@@ -114,7 +114,7 @@
 static void    print_error(const void *);
 static void    print_selftest(const void *);
 
-static const struct ataparams *getataparams(void);
+static void    fillataparams(void);
 
 static int     is_smart(void);
 
@@ -122,6 +122,10 @@
 static const   char *dvname;                   /* device name */
 static char    dvname_store[MAXPATHLEN];       /* for opendisk(3) */
 static const   char *cmdname;                  /* command user issued */
+static const   struct ataparams *inqbuf;       /* inquiry buffer */
+static char    model[sizeof(inqbuf->atap_model)+1];
+static char    revision[sizeof(inqbuf->atap_revision)+1];
+static char    serial[sizeof(inqbuf->atap_serial)+1];
 
 static void    device_identify(int, char *[]);
 static void    device_setidle(int, char *[]);
@@ -355,7 +359,9 @@
 static const struct attr_table micron_smart_names[] = {
        {   5,          "Reallocated NAND block count", NULL },
        { 173,          "Average block erase count", NULL },
+       { 181,          "Non 4K aligned access count", NULL },
        { 184,          "Error correction count", NULL },
+       { 189,          "Factory bad block count", NULL },
        { 197,          "Current pending ECC count", NULL },
        { 198,          "SMART offline scan uncorrectable error count", NULL },
        { 202,          "Percent lifetime remaining", NULL },
@@ -855,14 +861,19 @@
                print_selftest_entry(i, &stlog->log_entries[i]);
 }
 
-static const struct ataparams *
-getataparams(void)
+static void
+fillataparams(void)
 {
        struct atareq req;
        static union {
                unsigned char inbuf[DEV_BSIZE];
                struct ataparams inqbuf;
        } inbuf;
+       static int first = 1;
+
+       if (!first)
+               return;
+       first = 0;
 
        memset(&inbuf, 0, sizeof(inbuf));
        memset(&req, 0, sizeof(req));
@@ -875,7 +886,7 @@
 
        ata_command(&req);
 
-       return (&inbuf.inqbuf);
+       inqbuf = &inbuf.inqbuf;
 }
 
 /*
@@ -888,10 +899,9 @@
 is_smart(void)
 {
        int retval = 0;
-       const struct ataparams *inqbuf;
        const char *status;
 
-       inqbuf = getataparams();
+       fillataparams();
 
        if (inqbuf->atap_cmd_def != 0 && inqbuf->atap_cmd_def != 0xffff) {
                if (!(inqbuf->atap_cmd_set1 & WDC_CMD1_SMART)) {
@@ -951,8 +961,7 @@
 }
 
 static void
-compute_capacity(const struct ataparams *inqbuf, uint64_t *capacityp,
-    uint64_t *sectorsp, uint32_t *secsizep)
+compute_capacity(uint64_t *capacityp, uint64_t *sectorsp, uint32_t *secsizep)
 {
        uint64_t capacity;
        uint64_t sectors;
@@ -994,38 +1003,51 @@
 }
 
 /*
- * DEVICE COMMANDS
+ * Inspect the inqbuf and guess what vendor to use.  This list is fairly
+ * basic, and probably should be converted into a regexp scheme.
  */
+static const char *
+guess_vendor(void)
+{
+       struct {
+               const char *model;
+               const char *vendor;
+       } model_to_vendor[] = {
+               { "Crucial", "Micron" },
+               { "Micron", "Micron" },
+               { "C300-CT", "Micron" },
+               { "C400-MT", "Micron" },
+               { "M4-CT", "Micron" },
+               { "M500", "Micron" },
+               { "M510", "Micron" },
+               { "M550", "Micron" },
+               { "MTFDDA", "Micron" },
+               { "EEFDDA", "Micron" },
+       };
+       unsigned i;
+
+       for (i = 0; i < __arraycount(model_to_vendor); i++)
+               if (strncasecmp(model, model_to_vendor[i].model,
+                               strlen(model_to_vendor[i].model)) == 0)
+                       return model_to_vendor[i].vendor;
+
+       return NULL;
+}
 
 /*
- * device_identify:
- *
- *     Display the identity of the device
+ * identify_fixup() - Given an obtained ataparams, fix up the endian and
+ * other issues before using them.
  */
 static void
-device_identify(int argc, char *argv[])
+identify_fixup(void)
 {
-       const struct ataparams *inqbuf;
-       char model[sizeof(inqbuf->atap_model)+1];
-       char revision[sizeof(inqbuf->atap_revision)+1];
-       char serial[sizeof(inqbuf->atap_serial)+1];
-       char hnum[12];
-       uint64_t capacity;
-       uint64_t sectors;
-       uint32_t secsize;
-       int lb_per_pb;
        int needswap = 0;
-       int i;
-       uint8_t checksum;
-
-       /* No arguments. */
-       if (argc != 0)
-               usage();
-
-       inqbuf = getataparams();
 
        if ((inqbuf->atap_integrity & WDC_INTEGRITY_MAGIC_MASK) ==
            WDC_INTEGRITY_MAGIC) {
+               int i;
+               uint8_t checksum;
+
                for (i = checksum = 0; i < 512; i++)
                        checksum += ((const uint8_t *)inqbuf)[i];
                if (checksum != 0)
@@ -1062,6 +1084,33 @@
                inqbuf->atap_serial, sizeof(inqbuf->atap_serial),
                needswap);
 
+}
+
+/*
+ * DEVICE COMMANDS
+ */
+
+/*
+ * device_identify:
+ *
+ *     Display the identity of the device
+ */
+static void
+device_identify(int argc, char *argv[])
+{
+       char hnum[12];
+       uint64_t capacity;
+       uint64_t sectors;
+       uint32_t secsize;
+       int lb_per_pb;
+
+       /* No arguments. */
+       if (argc != 0)
+               usage();
+
+       fillataparams();
+       identify_fixup();
+
        printf("Model: %s, Rev: %s, Serial #: %s\n",
                model, revision, serial);
 
@@ -1081,7 +1130,7 @@
                 inqbuf->atap_config & ATA_CFG_FIXED ? "fixed" : "removable");
        printf("\n");
 
-       compute_capacity(inqbuf, &capacity, &sectors, &secsize);
+       compute_capacity(&capacity, &sectors, &secsize);
 
        humanize_number(hnum, sizeof(hnum), capacity, "bytes",
                HN_AUTOSCALE, HN_DIVISOR_1000);
@@ -1361,7 +1410,7 @@
                is_smart();
        } else if (strcmp(argv[0], "status") == 0) {
                int rv;
-               char *vendor = argc > 1 ? argv[1] : NULL;
+               const char *vendor = argc > 1 ? argv[1] : NULL;
 
                rv = is_smart();
 
@@ -1416,6 +1465,11 @@
 
                ata_command(&req);
 
+               if (!vendor || strcmp(vendor, "noauto") == 0) {
+                       fillataparams();
+                       identify_fixup();
+                       vendor = guess_vendor();
+               }
                print_smart_status(inbuf, inbuf2, vendor);
 
        } else if (strcmp(argv[0], "offline") == 0) {
@@ -1490,7 +1544,6 @@
 device_security(int argc, char *argv[])
 {
        struct atareq req;
-       const struct ataparams *inqbuf;
        unsigned char data[DEV_BSIZE];
        char *pass;
 
@@ -1500,7 +1553,7 @@
 
        memset(&req, 0, sizeof(req));
        if (strcmp(argv[0], "status") == 0) {
-               inqbuf = getataparams();
+               fillataparams();
                print_bitinfo("\t", "\n", inqbuf->atap_sec_st, ata_sec_st);
        } else if (strcmp(argv[0], "freeze") == 0) {
                req.command = WDCC_SECURITY_FREEZE;
@@ -1551,7 +1604,7 @@
                } else if (strcmp(argv[0], "erase") == 0) {
                        struct atareq prepare;
 
-                       inqbuf = getataparams();
+                       fillataparams();



Home | Main Index | Thread Index | Old Index