storaged: read emmc health data from sysfs
Sysfs data is straightforward so we don't need parsing anymore. Also removed periodical check since data is set only once during driver initialization. Checking at every device boot or storaged restart should be sufficient to monitor long term status change. Test: adb logcat -d -b events | grep storaged_emmc_info Bug: 36228467 Merged-In: I2a181f52c9f19de1e679a3a905aaebafe4d08227 Change-Id: Ic05e353f0af9363f3bcbe793ba0c351082e446ca
This commit is contained in:
parent
e98f1a9c56
commit
8197093497
7 changed files with 89 additions and 103 deletions
|
@ -1,6 +1,5 @@
|
|||
ro.storaged.event.interval # interval storaged scans for IO stats, in seconds
|
||||
ro.storaged.event.perf_check # check for time spent in event loop, in microseconds
|
||||
ro.storaged.disk_stats_pub # interval storaged publish disk stats, in seconds
|
||||
ro.storaged.emmc_info_pub # interval storaged publish emmc info, in seconds
|
||||
ro.storaged.uid_io.interval # interval storaged checks Per UID IO usage, in seconds
|
||||
ro.storaged.uid_io.threshold # Per UID IO usage limit, in bytes
|
||||
|
|
|
@ -230,7 +230,6 @@ public:
|
|||
// Periodic chores intervals in seconds
|
||||
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
|
||||
#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
|
||||
#define DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH ( 86400 )
|
||||
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
|
||||
#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)
|
||||
|
||||
|
@ -240,7 +239,6 @@ public:
|
|||
struct storaged_config {
|
||||
int periodic_chores_interval_unit;
|
||||
int periodic_chores_interval_disk_stats_publish;
|
||||
int periodic_chores_interval_emmc_info_publish;
|
||||
int periodic_chores_interval_uid_io;
|
||||
bool proc_uid_io_available; // whether uid_io is accessible
|
||||
bool diskstats_available; // whether diskstats is accessible
|
||||
|
@ -253,7 +251,6 @@ private:
|
|||
storaged_config mConfig;
|
||||
disk_stats_publisher mDiskStats;
|
||||
disk_stats_monitor mDsm;
|
||||
storage_info_t *info = nullptr;
|
||||
uid_monitor mUidm;
|
||||
time_t mStarttime;
|
||||
public:
|
||||
|
@ -264,9 +261,6 @@ public:
|
|||
void pause(void) {
|
||||
sleep(mConfig.periodic_chores_interval_unit);
|
||||
}
|
||||
void set_storage_info(storage_info_t *storage_info) {
|
||||
info = storage_info;
|
||||
}
|
||||
|
||||
time_t get_starttime(void) {
|
||||
return mStarttime;
|
||||
|
|
|
@ -24,43 +24,34 @@ friend class test_case_name##_##test_name##_Test
|
|||
|
||||
using namespace std;
|
||||
|
||||
// two characters in string for each byte
|
||||
struct str_hex {
|
||||
char str[2];
|
||||
};
|
||||
|
||||
class storage_info_t {
|
||||
protected:
|
||||
FRIEND_TEST(storaged_test, storage_info_t);
|
||||
uint8_t eol; // pre-eol (end of life) information
|
||||
uint8_t lifetime_a; // device life time estimation (type A)
|
||||
uint8_t lifetime_b; // device life time estimation (type B)
|
||||
uint16_t eol; // pre-eol (end of life) information
|
||||
uint16_t lifetime_a; // device life time estimation (type A)
|
||||
uint16_t lifetime_b; // device life time estimation (type B)
|
||||
string version; // version string
|
||||
public:
|
||||
void publish();
|
||||
public:
|
||||
storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0) {}
|
||||
virtual ~storage_info_t() {}
|
||||
virtual bool init() = 0;
|
||||
virtual bool update() = 0;
|
||||
virtual bool report() = 0;
|
||||
};
|
||||
|
||||
class emmc_info_t : public storage_info_t {
|
||||
private:
|
||||
// minimum size of a ext_csd file
|
||||
const int EXT_CSD_FILE_MIN_SIZE = 1024;
|
||||
// List of interesting offsets
|
||||
const size_t EXT_CSD_REV_IDX = 192 * sizeof(str_hex);
|
||||
const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(str_hex);
|
||||
const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(str_hex);
|
||||
const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(str_hex);
|
||||
|
||||
const char* ext_csd_file = "/d/mmc0/mmc0:0001/ext_csd";
|
||||
const char* emmc_ver_str[8] = {
|
||||
"4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
|
||||
const string emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
|
||||
const string emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
|
||||
const char* emmc_ver_str[9] = {
|
||||
"4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
|
||||
};
|
||||
public:
|
||||
virtual ~emmc_info_t() {}
|
||||
bool init();
|
||||
bool update();
|
||||
bool report();
|
||||
bool report_sysfs();
|
||||
bool report_debugfs();
|
||||
};
|
||||
|
||||
void report_storage_health();
|
||||
|
||||
#endif /* _STORAGED_INFO_H_ */
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#include <storaged_utils.h>
|
||||
|
||||
storaged_t storaged;
|
||||
emmc_info_t emmc_info;
|
||||
|
||||
// Function of storaged's main thread
|
||||
void* storaged_main(void* s) {
|
||||
|
@ -114,10 +113,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
|
||||
if (flag_main_service) { // start main thread
|
||||
if (emmc_info.init()) {
|
||||
storaged.set_storage_info(&emmc_info);
|
||||
}
|
||||
|
||||
report_storage_health();
|
||||
// Start the main thread of storaged
|
||||
pthread_t storaged_main_thread;
|
||||
errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged);
|
||||
|
|
|
@ -203,9 +203,6 @@ storaged_t::storaged_t(void) {
|
|||
mConfig.periodic_chores_interval_disk_stats_publish =
|
||||
property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH);
|
||||
|
||||
mConfig.periodic_chores_interval_emmc_info_publish =
|
||||
property_get_int32("ro.storaged.emmc_info_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH);
|
||||
|
||||
mConfig.periodic_chores_interval_uid_io =
|
||||
property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
|
||||
|
||||
|
@ -221,12 +218,6 @@ void storaged_t::event(void) {
|
|||
}
|
||||
}
|
||||
|
||||
if (info && mTimer &&
|
||||
(mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) {
|
||||
info->update();
|
||||
info->publish();
|
||||
}
|
||||
|
||||
if (mConfig.proc_uid_io_available && mTimer &&
|
||||
(mTimer % mConfig.periodic_chores_interval_uid_io) == 0) {
|
||||
mUidm.report();
|
||||
|
|
|
@ -16,83 +16,118 @@
|
|||
|
||||
#define LOG_TAG "storaged"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/parseint.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <log/log_event_list.h>
|
||||
|
||||
#include "storaged.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace android;
|
||||
using namespace android::base;
|
||||
|
||||
void report_storage_health()
|
||||
{
|
||||
emmc_info_t mmc;
|
||||
mmc.report();
|
||||
}
|
||||
|
||||
void storage_info_t::publish()
|
||||
{
|
||||
if (eol == 0 && lifetime_a == 0 && lifetime_b == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
android_log_event_list(EVENTLOGTAG_EMMCINFO)
|
||||
<< version << eol << lifetime_a << lifetime_b
|
||||
<< LOG_ID_EVENTS;
|
||||
}
|
||||
|
||||
bool emmc_info_t::init()
|
||||
bool emmc_info_t::report()
|
||||
{
|
||||
if (!report_sysfs() && !report_debugfs())
|
||||
return false;
|
||||
|
||||
publish();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool emmc_info_t::report_sysfs()
|
||||
{
|
||||
string buffer;
|
||||
if (!ReadFileToString(ext_csd_file, &buffer) ||
|
||||
buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
|
||||
uint16_t rev = 0;
|
||||
|
||||
if (!ReadFileToString(emmc_sysfs + "rev", &buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string ver_str = buffer.substr(EXT_CSD_REV_IDX, sizeof(str_hex));
|
||||
uint8_t ext_csd_rev;
|
||||
if (!ParseUint(ver_str, &ext_csd_rev)) {
|
||||
LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV.";
|
||||
if (sscanf(buffer.c_str(), "0x%hx", &rev) < 1 ||
|
||||
rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
version = "emmc ";
|
||||
version += (ext_csd_rev < ARRAY_SIZE(emmc_ver_str)) ?
|
||||
emmc_ver_str[ext_csd_rev] : "Unknown";
|
||||
version += emmc_ver_str[rev];
|
||||
|
||||
if (ext_csd_rev < 7) {
|
||||
if (!ReadFileToString(emmc_sysfs + "pre_eol_info", &buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return update();
|
||||
}
|
||||
|
||||
bool emmc_info_t::update()
|
||||
{
|
||||
string buffer;
|
||||
if (!ReadFileToString(ext_csd_file, &buffer) ||
|
||||
buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
|
||||
if (sscanf(buffer.c_str(), "%hx", &eol) < 1 || eol == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string str = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(str_hex));
|
||||
if (!ParseUint(str, &eol)) {
|
||||
LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO.";
|
||||
if (!ReadFileToString(emmc_sysfs + "life_time", &buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(str_hex));
|
||||
if (!ParseUint(str, &lifetime_a)) {
|
||||
LOG_TO(SYSTEM, ERROR)
|
||||
<< "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A.";
|
||||
return false;
|
||||
}
|
||||
|
||||
str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(str_hex));
|
||||
if (!ParseUint(str, &lifetime_b)) {
|
||||
LOG_TO(SYSTEM, ERROR)
|
||||
<< "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B.";
|
||||
if (sscanf(buffer.c_str(), "0x%hx 0x%hx", &lifetime_a, &lifetime_b) < 2 ||
|
||||
(lifetime_a == 0 && lifetime_b == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t EXT_CSD_FILE_MIN_SIZE = 1024;
|
||||
/* 2 characters in string for each byte */
|
||||
const size_t EXT_CSD_REV_IDX = 192 * 2;
|
||||
const size_t EXT_PRE_EOL_INFO_IDX = 267 * 2;
|
||||
const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * 2;
|
||||
const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * 2;
|
||||
|
||||
bool emmc_info_t::report_debugfs()
|
||||
{
|
||||
string buffer;
|
||||
uint16_t rev = 0;
|
||||
|
||||
if (!ReadFileToString(emmc_debugfs, &buffer) ||
|
||||
buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string str = buffer.substr(EXT_CSD_REV_IDX, 2);
|
||||
if (!ParseUint(str, &rev) ||
|
||||
rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
version = "emmc ";
|
||||
version += emmc_ver_str[rev];
|
||||
|
||||
str = buffer.substr(EXT_PRE_EOL_INFO_IDX, 2);
|
||||
if (!ParseUint(str, &eol)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, 2);
|
||||
if (!ParseUint(str, &lifetime_a)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, 2);
|
||||
if (!ParseUint(str, &lifetime_b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat"
|
||||
#define SDA_DISK_STATS_PATH "/sys/block/sda/stat"
|
||||
#define EMMC_EXT_CSD_PATH "/d/mmc0/mmc0:0001/ext_csd"
|
||||
|
||||
static void pause(uint32_t sec) {
|
||||
const char* path = "/cache/test";
|
||||
|
@ -58,13 +57,8 @@ static void pause(uint32_t sec) {
|
|||
const char* DISK_STATS_PATH;
|
||||
TEST(storaged_test, retvals) {
|
||||
struct disk_stats stats;
|
||||
emmc_info_t info;
|
||||
memset(&stats, 0, sizeof(struct disk_stats));
|
||||
|
||||
if (info.init()) {
|
||||
EXPECT_TRUE(info.update());
|
||||
}
|
||||
|
||||
if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
|
||||
DISK_STATS_PATH = MMC_DISK_STATS_PATH;
|
||||
} else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) {
|
||||
|
@ -127,20 +121,6 @@ TEST(storaged_test, disk_stats) {
|
|||
}
|
||||
}
|
||||
|
||||
TEST(storaged_test, storage_info_t) {
|
||||
emmc_info_t info;
|
||||
|
||||
if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) {
|
||||
int ret = info.init();
|
||||
if (ret) {
|
||||
EXPECT_TRUE(info.version.empty());
|
||||
ASSERT_TRUE(info.update());
|
||||
// update should put something in info.
|
||||
EXPECT_TRUE(info.eol || info.lifetime_a || info.lifetime_b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static double mean(std::deque<uint32_t> nums) {
|
||||
double sum = 0.0;
|
||||
for (uint32_t i : nums) {
|
||||
|
|
Loading…
Reference in a new issue