| #!/bin/sh -u |
| # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| . /usr/share/misc/storage-info-common.sh |
| . /usr/share/misc/shflags |
| |
| DEFINE_boolean 'test' ${FLAGS_FALSE} "For unit testing." |
| |
| # Parse command line. |
| FLAGS "$@" || exit 1 |
| eval set -- "${FLAGS_ARGV}" |
| |
| # This file is used for userfeedback as well. |
| STORAGE_INFO_FILE="/var/log/storage_info.txt" |
| INVALID="-1" |
| |
| # Report disk health from SMART (S.M.A.R.T.) parameters. |
| # usage: |
| # report_smart_metrics <uncorrectable-errors> <transfer-errors> |
| report_smart_metrics() { |
| if [ -n "$1" ]; then |
| if [ $1 -ne ${INVALID} ]; then |
| metrics_client Platform.SmartUncorrectableErrors $1 1 1000000 20 |
| fi |
| fi |
| if [ -n "$2" ]; then |
| if [ $2 -ne ${INVALID} ]; then |
| metrics_client Platform.SmartTransferErrors $2 1 1000000 20 |
| fi |
| fi |
| } |
| |
| # Sata information. |
| GET_SMART_ERRORS=' |
| $2 == "Reported_Uncorrect" { uncorr = $8 } |
| $2 == "UDMA_CRC_Error_Count" { txfer = $8 } |
| END { print uncorr, txfer } |
| ' |
| |
| sata_disk_metrics() { |
| # Extract revelevant SMART information from this file, if any. |
| report_smart_metrics $(awk -v uncorr="${INVALID}" -v txfer="${INVALID}" \ |
| "${GET_SMART_ERRORS}" "${STORAGE_INFO_FILE}") |
| } |
| |
| emmc_disk_metrics() { |
| local life type |
| |
| # Extract revelevant eMMC information from this file, if any. |
| for type in 'A' 'B'; do |
| life="$(sed -ne "/DEVICE_LIFE_TIME_EST_TYP_${type}/s/.*: \(0x.*\)]$/\1/p" \ |
| "${STORAGE_INFO_FILE}")" |
| if [ -n "${life}" ]; then |
| metrics_client -s "Platform.Emmc.LifeUsed.Type${type}" \ |
| "$(printf "%d" "${life}")" |
| fi |
| done |
| } |
| |
| sindin8de2_disk_metrics() { |
| # Sandisk SDIN8DE2-*G 4.51 stores eMMC device health in vendor registers: |
| # 94: MLC Device health. |
| # 87: SLC Device health. |
| local offset_A=94 |
| local offset_B=87 |
| local offset life type |
| |
| if grep -qe "^name.*SEM..G" "${STORAGE_INFO_FILE}"; then |
| for type in 'A' 'B'; do |
| eval "offset=\"\${offset_${type}}\"" |
| |
| life="$(sed -ne "/Vendor Specific Fields \[VENDOR_SPECIFIC_FIELD\[${offset}\]\]:/s/.*: \(0x.*\)$/\1/p" \ |
| "${STORAGE_INFO_FILE}")" |
| if [ -n "${life}" ]; then |
| metrics_client -s "Platform.Emmc.LifeUsed.Type${type}" \ |
| "$(printf "%d" "${life}")" |
| fi |
| done |
| fi |
| } |
| |
| # Invoke main if not in test mode, otherwise let the test code call. |
| main() { |
| if [ ${FLAGS_test} -eq ${FLAGS_TRUE} ]; then |
| return |
| fi |
| if [ $# -ne 0 ]; then |
| flags_help |
| exit 1 |
| fi |
| rm -f "${STORAGE_INFO_FILE}" |
| get_storage_info > "${STORAGE_INFO_FILE}" |
| sata_disk_metrics |
| emmc_disk_metrics |
| sindin8de2_disk_metrics |
| } |
| main "$@" |