1# Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import logging, os, re 6from autotest_lib.client.bin import test, utils 7from autotest_lib.client.common_lib import error 8 9 10class hardware_StorageWearoutDetect(test.test): 11 """ 12 Check wear out status for storage device available in SMART for SSD and 13 in ext_csd for eMMC version 5.0 or later. For previous version of eMMC, 14 it will be treat as data not available. 15 16 The test will be failed if: 17 - At least one SMART variable has value under its threshold 18 or 19 - eMMC wear out status variable is in 90-100% band or higher ( 20 DEVICE_LIFE_TIME_EST_TYP_A). Seeing this consistently means the lab 21 device may have to be replaced. 22 """ 23 24 version = 1 25 STORAGE_INFO_PATH = '/var/log/storage_info.txt' 26 STORAGE_INFO_COMMON_PATH = '/usr/share/misc/storage-info-common.sh' 27 28 # Example " Model Number: LITEONIT LSS-32L6G-HP" 29 SSD_DETECT = r"\s*Model Number:\s*(?P<model>.*)\s*$" 30 31 # Example " Extended CSD rev 1.7 (MMC 5.0)" 32 MMC_DETECT = r"\s*Extended CSD rev.*MMC (?P<version>\d+.\d+)" 33 34 # Field meaning and example line that have failing attribute 35 # ID# ATTRIBUTE_NAME FLAGS VALUE WORST THRESH FAIL RAW_VALUE 36 # 184 End-to-End_Error PO--CK 001 001 097 NOW 135 37 SSD_FAIL = r"""\s*(?P<param>\S+\s\S+) # ID and attribute name 38 \s+[P-][O-][S-][R-][C-][K-] # flags 39 (\s+\d{3}){3} # three 3-digits numbers 40 \s+NOW # fail indicator""" 41 42 # Ex "Device life time estimation type A [DEVICE_LIFE_TIME_EST_TYP_A: 0x01]" 43 # 0x0a means 90-100% band, 0x0b means over 100% band -> find not digit 44 MMC_FAIL = r".*(?P<param>DEVICE_LIFE_TIME_EST_TYP_.): 0x0\D" 45 46 47 def run_once(self, use_cached_result=True): 48 """ 49 Run the test 50 51 @param use_cached_result: Use the result that generated when machine 52 booted or generate new one. 53 """ 54 55 if not use_cached_result: 56 if not os.path.exists(self.STORAGE_INFO_COMMON_PATH): 57 msg = str('Test failed with error: %s not exist' 58 % self.STORAGE_INFO_COMMON_PATH) 59 raise error.TestFail(msg) 60 cmd = ' '.join(['. %s;' % (self.STORAGE_INFO_COMMON_PATH, ), 61 'get_storage_info']) 62 utils.run(cmd, stdout_tee=open(self.STORAGE_INFO_PATH, 'w'), 63 stderr_tee=utils.TEE_TO_LOGS) 64 65 # Check that storage_info file exist. 66 if not os.path.exists(self.STORAGE_INFO_PATH): 67 msg = str('Test failed with error: %s not exist' 68 % self.STORAGE_INFO_PATH) 69 raise error.TestFail(msg) 70 71 mmc_detect = False 72 ssd_detect = False 73 legacy_mmc = False 74 fail_msg = '' 75 76 with open(self.STORAGE_INFO_PATH) as f: 77 for line in f: 78 m = re.match(self.SSD_DETECT, line) 79 if m: 80 model = m.group('model') 81 ssd_detect = True 82 logging.info('Found SSD model %s', model) 83 84 m = re.match(self.MMC_DETECT, line) 85 if m: 86 version = m.group('version') 87 if float(version) < 5.0: 88 legacy_mmc = True 89 mmc_detect = True 90 logging.info('Found eMMC version %s', version) 91 92 m = re.match(self.SSD_FAIL, line, re.X) 93 if m: 94 param = m.group('param') 95 fail_msg += 'SSD failure ' + param 96 97 m = re.match(self.MMC_FAIL, line) 98 if m: 99 param = m.group('param') 100 fail_msg += 'MMC failure ' + param 101 102 if not ssd_detect and not mmc_detect: 103 raise error.TestFail('Can not detect storage device.') 104 105 if fail_msg: 106 msg = 'Detected wearout parameter:%s' % fail_msg 107 raise error.TestFail(msg) 108 109 if legacy_mmc: 110 msg = 'eMMC version %s detected. ' % version 111 msg += 'Wearout attributes are supported in eMMC 5.0 and later.' 112 logging.info(msg) 113