• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import logging
7import os
8
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11
12DEFAULT_MIN_GB = 16
13# Allowable amount of bits eMMC vendor can use in firmware to support bad block
14# replacement and metadata.
15EMMC_VENDOR_ALLOWED_GB = 0.25
16# Amount of data available for user data in device, the rest is left for
17# over provisioning.
18# Typically a SATA device will use 7% over provisioning [the difference
19# between GB and GiB], but some eMMC device can use 9%.
20# With Flash becoming more error prone as lithography shrinks, the trend
21# is to increase over provisioning.
22DEFAULT_USER_DENSITY = 0.9
23
24
25class hardware_DiskSize(test.test):
26    """
27    Check that disk size is around 16GB at least.
28    """
29
30    version = 1
31
32    def _is_emmc(self):
33        path = os.path.join("/sys/class/block/", self._device,
34                            "device", "type")
35        if not os.path.exists(path):
36            return False
37        return utils.read_one_line(path) == 'MMC'
38
39
40    @classmethod
41    def _gib_to_gb(cls, gib):
42        return float(gib) * (1 << 30) / (10 ** 9)
43
44    def _compute_min_gb(self):
45        """Computes minimum size allowed primary storage device.
46
47        TODO(tbroch): Add computation of raw bytes in eMMC using 'Chip Specific
48        Data' (CSD & EXT_CSD) defined by JEDEC JESD84-A44.pdf if possible.
49
50        CSD :: /sys/class/block/<device>/device/csd
51        EXT_CSD :: debugfs
52
53        Algorithm should look something like this:
54        CSD[C_SIZE] = 0xfff == eMMC > 2GB
55        EXT_CSD[SEC_COUNT] = # of 512byte sectors
56
57        Now for existing eMMC I've examined I do see the C_SIZE == 0xfff.
58        Unfortunately the SEC_COUNT appears to have excluded the sectors
59        reserved for metadata & repair.  Perhaps thats by design in which case
60        there is no mechanism to determine the actual raw sectors.
61
62        For now I use 0.25GB as an acceptable fudge.
63
64        Returns:
65            integer, in GB of minimum storage size.
66        """
67
68        min_gb = DEFAULT_MIN_GB
69        if self._is_emmc():
70            min_gb -= EMMC_VENDOR_ALLOWED_GB
71        min_gb *= DEFAULT_USER_DENSITY
72        return self._gib_to_gb(min_gb)
73
74
75    def run_once(self):
76        root_dev = utils.get_root_device()
77        self._device = os.path.basename(root_dev)
78        disk_size = utils.get_disk_size(root_dev)
79        if not disk_size:
80            raise error.TestError('Unable to determine main disk size')
81
82        # Capacity of a hard disk is quoted with SI prefixes, incrementing by
83        # powers of 1000, instead of powers of 1024.
84        gb = float(disk_size) / (10 ** 9)
85
86        self.write_perf_keyval({"gb_main_disk_size": gb})
87        min_gb = self._compute_min_gb()
88        logging.info("DiskSize: %.3f GB MinDiskSize: %.3f GB", gb, min_gb)
89        if (gb < min_gb):
90            raise error.TestError("DiskSize %.3f GB below minimum (%.3f GB)" \
91                % (gb, min_gb))
92