Print this page
8074 need to add FMA event for SSD wearout


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.

  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 /*
  29  * Disk status library
  30  *
  31  * This library is responsible for querying health and other status information
  32  * from disk drives.  It is intended to be a generic interface, however only
  33  * SCSI (and therefore SATA) disks are currently supported.  The library is
  34  * capable of detecting the following status conditions:
  35  *
  36  *      - Predictive failure
  37  *      - Overtemp
  38  *      - Self-test failure

  39  */
  40 
  41 #include <assert.h>
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <libdevinfo.h>
  45 #include <libdiskstatus.h>
  46 #include <stdlib.h>
  47 #include <string.h>
  48 #include <sys/fm/io/scsi.h>
  49 #include <sys/stat.h>
  50 #include <unistd.h>
  51 
  52 #include "ds_impl.h"
  53 #include "ds_scsi.h"
  54 
  55 static ds_transport_t *ds_transports[] = {
  56         &ds_scsi_sim_transport,
  57         &ds_scsi_uscsi_transport
  58 };


 114 
 115         if (dsp->ds_error == EDS_NO_TRANSPORT) {
 116                 *error = dsp->ds_error;
 117                 disk_status_close(dsp);
 118                 return (NULL);
 119         }
 120 
 121         return (dsp);
 122 }
 123 
 124 /*
 125  * Close a handle to a disk.
 126  */
 127 void
 128 disk_status_close(disk_status_t *dsp)
 129 {
 130         nvlist_free(dsp->ds_state);
 131         nvlist_free(dsp->ds_predfail);
 132         nvlist_free(dsp->ds_overtemp);
 133         nvlist_free(dsp->ds_testfail);

 134         if (dsp->ds_data)
 135                 dsp->ds_transport->dt_close(dsp->ds_data);
 136         (void) close(dsp->ds_fd);
 137         free(dsp->ds_path);
 138         free(dsp);
 139 }
 140 
 141 void
 142 disk_status_set_debug(boolean_t value)
 143 {
 144         ds_debug = value;
 145 }
 146 
 147 /*
 148  * Query basic information
 149  */
 150 const char *
 151 disk_status_path(disk_status_t *dsp)
 152 {
 153         return (dsp->ds_path);


 155 
 156 int
 157 disk_status_errno(disk_status_t *dsp)
 158 {
 159         return (dsp->ds_error);
 160 }
 161 
 162 nvlist_t *
 163 disk_status_get(disk_status_t *dsp)
 164 {
 165         nvlist_t *nvl = NULL;
 166         nvlist_t *faults = NULL;
 167         int err;
 168 
 169         /*
 170          * Scan (or rescan) the current device.
 171          */
 172         nvlist_free(dsp->ds_testfail);
 173         nvlist_free(dsp->ds_predfail);
 174         nvlist_free(dsp->ds_overtemp);


 175         dsp->ds_testfail = dsp->ds_overtemp = dsp->ds_predfail = NULL;
 176         dsp->ds_faults = 0;
 177 
 178         /*
 179          * Even if there is an I/O failure when trying to scan the device, we
 180          * can still return the current state.
 181          */
 182         if (dsp->ds_transport->dt_scan(dsp->ds_data) != 0 &&
 183             dsp->ds_error != EDS_IO)
 184                 return (NULL);
 185 
 186         if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 187                 goto nverror;
 188 
 189         if ((err = nvlist_add_string(nvl, "protocol", "scsi")) != 0 ||
 190             (err = nvlist_add_nvlist(nvl, "status", dsp->ds_state)) != 0)
 191                 goto nverror;
 192 
 193         /*
 194          * Construct the list of faults.


 205                         goto nverror;
 206         }
 207 
 208         if (dsp->ds_testfail != NULL) {
 209                 if ((err = nvlist_add_boolean_value(faults,
 210                     FM_EREPORT_SCSI_TESTFAIL,
 211                     (dsp->ds_faults & DS_FAULT_TESTFAIL) != 0)) != 0 ||
 212                     (err = nvlist_add_nvlist(nvl, FM_EREPORT_SCSI_TESTFAIL,
 213                     dsp->ds_testfail)) != 0)
 214                         goto nverror;
 215         }
 216 
 217         if (dsp->ds_overtemp != NULL) {
 218                 if ((err = nvlist_add_boolean_value(faults,
 219                     FM_EREPORT_SCSI_OVERTEMP,
 220                     (dsp->ds_faults & DS_FAULT_OVERTEMP) != 0)) != 0 ||
 221                     (err = nvlist_add_nvlist(nvl, FM_EREPORT_SCSI_OVERTEMP,
 222                     dsp->ds_overtemp)) != 0)
 223                         goto nverror;
 224         }









 225 
 226         if ((err = nvlist_add_nvlist(nvl, "faults", faults)) != 0)
 227                 goto nverror;
 228 
 229         nvlist_free(faults);
 230         return (nvl);
 231 
 232 nverror:
 233         assert(err == ENOMEM);
 234         nvlist_free(nvl);
 235         nvlist_free(faults);
 236         (void) ds_set_errno(dsp, EDS_NOMEM);
 237         return (NULL);
 238 }


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  25  */
  26 


  27 /*
  28  * Disk status library
  29  *
  30  * This library is responsible for querying health and other status information
  31  * from disk drives.  It is intended to be a generic interface, however only
  32  * SCSI (and therefore SATA) disks are currently supported.  The library is
  33  * capable of detecting the following status conditions:
  34  *
  35  *      - Predictive failure
  36  *      - Overtemp
  37  *      - Self-test failure
  38  *      - Solid State Media wearout
  39  */
  40 
  41 #include <assert.h>
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <libdevinfo.h>
  45 #include <libdiskstatus.h>
  46 #include <stdlib.h>
  47 #include <string.h>
  48 #include <sys/fm/io/scsi.h>
  49 #include <sys/stat.h>
  50 #include <unistd.h>
  51 
  52 #include "ds_impl.h"
  53 #include "ds_scsi.h"
  54 
  55 static ds_transport_t *ds_transports[] = {
  56         &ds_scsi_sim_transport,
  57         &ds_scsi_uscsi_transport
  58 };


 114 
 115         if (dsp->ds_error == EDS_NO_TRANSPORT) {
 116                 *error = dsp->ds_error;
 117                 disk_status_close(dsp);
 118                 return (NULL);
 119         }
 120 
 121         return (dsp);
 122 }
 123 
 124 /*
 125  * Close a handle to a disk.
 126  */
 127 void
 128 disk_status_close(disk_status_t *dsp)
 129 {
 130         nvlist_free(dsp->ds_state);
 131         nvlist_free(dsp->ds_predfail);
 132         nvlist_free(dsp->ds_overtemp);
 133         nvlist_free(dsp->ds_testfail);
 134         nvlist_free(dsp->ds_ssmwearout);
 135         if (dsp->ds_data)
 136                 dsp->ds_transport->dt_close(dsp->ds_data);
 137         (void) close(dsp->ds_fd);
 138         free(dsp->ds_path);
 139         free(dsp);
 140 }
 141 
 142 void
 143 disk_status_set_debug(boolean_t value)
 144 {
 145         ds_debug = value;
 146 }
 147 
 148 /*
 149  * Query basic information
 150  */
 151 const char *
 152 disk_status_path(disk_status_t *dsp)
 153 {
 154         return (dsp->ds_path);


 156 
 157 int
 158 disk_status_errno(disk_status_t *dsp)
 159 {
 160         return (dsp->ds_error);
 161 }
 162 
 163 nvlist_t *
 164 disk_status_get(disk_status_t *dsp)
 165 {
 166         nvlist_t *nvl = NULL;
 167         nvlist_t *faults = NULL;
 168         int err;
 169 
 170         /*
 171          * Scan (or rescan) the current device.
 172          */
 173         nvlist_free(dsp->ds_testfail);
 174         nvlist_free(dsp->ds_predfail);
 175         nvlist_free(dsp->ds_overtemp);
 176         nvlist_free(dsp->ds_ssmwearout);
 177         dsp->ds_ssmwearout = NULL;
 178         dsp->ds_testfail = dsp->ds_overtemp = dsp->ds_predfail = NULL;
 179         dsp->ds_faults = 0;
 180 
 181         /*
 182          * Even if there is an I/O failure when trying to scan the device, we
 183          * can still return the current state.
 184          */
 185         if (dsp->ds_transport->dt_scan(dsp->ds_data) != 0 &&
 186             dsp->ds_error != EDS_IO)
 187                 return (NULL);
 188 
 189         if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
 190                 goto nverror;
 191 
 192         if ((err = nvlist_add_string(nvl, "protocol", "scsi")) != 0 ||
 193             (err = nvlist_add_nvlist(nvl, "status", dsp->ds_state)) != 0)
 194                 goto nverror;
 195 
 196         /*
 197          * Construct the list of faults.


 208                         goto nverror;
 209         }
 210 
 211         if (dsp->ds_testfail != NULL) {
 212                 if ((err = nvlist_add_boolean_value(faults,
 213                     FM_EREPORT_SCSI_TESTFAIL,
 214                     (dsp->ds_faults & DS_FAULT_TESTFAIL) != 0)) != 0 ||
 215                     (err = nvlist_add_nvlist(nvl, FM_EREPORT_SCSI_TESTFAIL,
 216                     dsp->ds_testfail)) != 0)
 217                         goto nverror;
 218         }
 219 
 220         if (dsp->ds_overtemp != NULL) {
 221                 if ((err = nvlist_add_boolean_value(faults,
 222                     FM_EREPORT_SCSI_OVERTEMP,
 223                     (dsp->ds_faults & DS_FAULT_OVERTEMP) != 0)) != 0 ||
 224                     (err = nvlist_add_nvlist(nvl, FM_EREPORT_SCSI_OVERTEMP,
 225                     dsp->ds_overtemp)) != 0)
 226                         goto nverror;
 227         }
 228 
 229         if (dsp->ds_ssmwearout != NULL) {
 230                 if ((err = nvlist_add_boolean_value(faults,
 231                     FM_EREPORT_SCSI_SSMWEAROUT,
 232                     (dsp->ds_faults & DS_FAULT_SSMWEAROUT) != 0)) != 0 ||
 233                     (err = nvlist_add_nvlist(nvl, FM_EREPORT_SCSI_SSMWEAROUT,
 234                     dsp->ds_ssmwearout)) != 0)
 235                         goto nverror;
 236         }
 237 
 238         if ((err = nvlist_add_nvlist(nvl, "faults", faults)) != 0)
 239                 goto nverror;
 240 
 241         nvlist_free(faults);
 242         return (nvl);
 243 
 244 nverror:
 245         assert(err == ENOMEM);
 246         nvlist_free(nvl);
 247         nvlist_free(faults);
 248         (void) ds_set_errno(dsp, EDS_NOMEM);
 249         return (NULL);
 250 }