summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJin Qian2017-03-17 18:36:59 -0500
committerJin Qian2017-04-03 11:48:14 -0500
commit8197093497a65829f4da90b3fda0e281da7b27eb (patch)
treea099952c1a719453f9d4ffe56ef5f2dce10b66b1 /storaged
parente98f1a9c5607e13da5fccafd1cd6f5414319e4ea (diff)
downloadplatform-system-core-8197093497a65829f4da90b3fda0e281da7b27eb.tar.gz
platform-system-core-8197093497a65829f4da90b3fda0e281da7b27eb.tar.xz
platform-system-core-8197093497a65829f4da90b3fda0e281da7b27eb.zip
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
Diffstat (limited to 'storaged')
-rw-r--r--storaged/README.properties1
-rw-r--r--storaged/include/storaged.h6
-rw-r--r--storaged/include/storaged_info.h39
-rw-r--r--storaged/main.cpp6
-rw-r--r--storaged/storaged.cpp9
-rw-r--r--storaged/storaged_info.cpp91
-rw-r--r--storaged/tests/storaged_test.cpp20
7 files changed, 79 insertions, 93 deletions
diff --git a/storaged/README.properties b/storaged/README.properties
index 70e6026f0..2d8397fc8 100644
--- a/storaged/README.properties
+++ b/storaged/README.properties
@@ -1,6 +1,5 @@
1ro.storaged.event.interval # interval storaged scans for IO stats, in seconds 1ro.storaged.event.interval # interval storaged scans for IO stats, in seconds
2ro.storaged.event.perf_check # check for time spent in event loop, in microseconds 2ro.storaged.event.perf_check # check for time spent in event loop, in microseconds
3ro.storaged.disk_stats_pub # interval storaged publish disk stats, in seconds 3ro.storaged.disk_stats_pub # interval storaged publish disk stats, in seconds
4ro.storaged.emmc_info_pub # interval storaged publish emmc info, in seconds
5ro.storaged.uid_io.interval # interval storaged checks Per UID IO usage, in seconds 4ro.storaged.uid_io.interval # interval storaged checks Per UID IO usage, in seconds
6ro.storaged.uid_io.threshold # Per UID IO usage limit, in bytes 5ro.storaged.uid_io.threshold # Per UID IO usage limit, in bytes
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index bd1391c98..b6a0850c8 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -230,7 +230,6 @@ public:
230// Periodic chores intervals in seconds 230// Periodic chores intervals in seconds
231#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 ) 231#define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
232#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 ) 232#define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
233#define DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH ( 86400 )
234#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 ) 233#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
235#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300) 234#define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)
236 235
@@ -240,7 +239,6 @@ public:
240struct storaged_config { 239struct storaged_config {
241 int periodic_chores_interval_unit; 240 int periodic_chores_interval_unit;
242 int periodic_chores_interval_disk_stats_publish; 241 int periodic_chores_interval_disk_stats_publish;
243 int periodic_chores_interval_emmc_info_publish;
244 int periodic_chores_interval_uid_io; 242 int periodic_chores_interval_uid_io;
245 bool proc_uid_io_available; // whether uid_io is accessible 243 bool proc_uid_io_available; // whether uid_io is accessible
246 bool diskstats_available; // whether diskstats is accessible 244 bool diskstats_available; // whether diskstats is accessible
@@ -253,7 +251,6 @@ private:
253 storaged_config mConfig; 251 storaged_config mConfig;
254 disk_stats_publisher mDiskStats; 252 disk_stats_publisher mDiskStats;
255 disk_stats_monitor mDsm; 253 disk_stats_monitor mDsm;
256 storage_info_t *info = nullptr;
257 uid_monitor mUidm; 254 uid_monitor mUidm;
258 time_t mStarttime; 255 time_t mStarttime;
259public: 256public:
@@ -264,9 +261,6 @@ public:
264 void pause(void) { 261 void pause(void) {
265 sleep(mConfig.periodic_chores_interval_unit); 262 sleep(mConfig.periodic_chores_interval_unit);
266 } 263 }
267 void set_storage_info(storage_info_t *storage_info) {
268 info = storage_info;
269 }
270 264
271 time_t get_starttime(void) { 265 time_t get_starttime(void) {
272 return mStarttime; 266 return mStarttime;
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index cb5b8a8e2..cfcdd7f22 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -24,43 +24,34 @@ friend class test_case_name##_##test_name##_Test
24 24
25using namespace std; 25using namespace std;
26 26
27// two characters in string for each byte
28struct str_hex {
29 char str[2];
30};
31
32class storage_info_t { 27class storage_info_t {
33protected: 28protected:
34 FRIEND_TEST(storaged_test, storage_info_t); 29 FRIEND_TEST(storaged_test, storage_info_t);
35 uint8_t eol; // pre-eol (end of life) information 30 uint16_t eol; // pre-eol (end of life) information
36 uint8_t lifetime_a; // device life time estimation (type A) 31 uint16_t lifetime_a; // device life time estimation (type A)
37 uint8_t lifetime_b; // device life time estimation (type B) 32 uint16_t lifetime_b; // device life time estimation (type B)
38 string version; // version string 33 string version; // version string
39public:
40 void publish(); 34 void publish();
35public:
36 storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0) {}
41 virtual ~storage_info_t() {} 37 virtual ~storage_info_t() {}
42 virtual bool init() = 0; 38 virtual bool report() = 0;
43 virtual bool update() = 0;
44}; 39};
45 40
46class emmc_info_t : public storage_info_t { 41class emmc_info_t : public storage_info_t {
47private: 42private:
48 // minimum size of a ext_csd file 43 const string emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
49 const int EXT_CSD_FILE_MIN_SIZE = 1024; 44 const string emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
50 // List of interesting offsets 45 const char* emmc_ver_str[9] = {
51 const size_t EXT_CSD_REV_IDX = 192 * sizeof(str_hex); 46 "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
52 const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(str_hex);
53 const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(str_hex);
54 const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(str_hex);
55
56 const char* ext_csd_file = "/d/mmc0/mmc0:0001/ext_csd";
57 const char* emmc_ver_str[8] = {
58 "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
59 }; 47 };
60public: 48public:
61 virtual ~emmc_info_t() {} 49 virtual ~emmc_info_t() {}
62 bool init(); 50 bool report();
63 bool update(); 51 bool report_sysfs();
52 bool report_debugfs();
64}; 53};
65 54
55void report_storage_health();
56
66#endif /* _STORAGED_INFO_H_ */ 57#endif /* _STORAGED_INFO_H_ */
diff --git a/storaged/main.cpp b/storaged/main.cpp
index e25298b12..2f2273dc1 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -43,7 +43,6 @@
43#include <storaged_utils.h> 43#include <storaged_utils.h>
44 44
45storaged_t storaged; 45storaged_t storaged;
46emmc_info_t emmc_info;
47 46
48// Function of storaged's main thread 47// Function of storaged's main thread
49void* storaged_main(void* s) { 48void* storaged_main(void* s) {
@@ -114,10 +113,7 @@ int main(int argc, char** argv) {
114 } 113 }
115 114
116 if (flag_main_service) { // start main thread 115 if (flag_main_service) { // start main thread
117 if (emmc_info.init()) { 116 report_storage_health();
118 storaged.set_storage_info(&emmc_info);
119 }
120
121 // Start the main thread of storaged 117 // Start the main thread of storaged
122 pthread_t storaged_main_thread; 118 pthread_t storaged_main_thread;
123 errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged); 119 errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged);
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 88fbb7a3c..72bb6e23d 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -203,9 +203,6 @@ storaged_t::storaged_t(void) {
203 mConfig.periodic_chores_interval_disk_stats_publish = 203 mConfig.periodic_chores_interval_disk_stats_publish =
204 property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH); 204 property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH);
205 205
206 mConfig.periodic_chores_interval_emmc_info_publish =
207 property_get_int32("ro.storaged.emmc_info_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH);
208
209 mConfig.periodic_chores_interval_uid_io = 206 mConfig.periodic_chores_interval_uid_io =
210 property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO); 207 property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
211 208
@@ -221,12 +218,6 @@ void storaged_t::event(void) {
221 } 218 }
222 } 219 }
223 220
224 if (info && mTimer &&
225 (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) {
226 info->update();
227 info->publish();
228 }
229
230 if (mConfig.proc_uid_io_available && mTimer && 221 if (mConfig.proc_uid_io_available && mTimer &&
231 (mTimer % mConfig.periodic_chores_interval_uid_io) == 0) { 222 (mTimer % mConfig.periodic_chores_interval_uid_io) == 0) {
232 mUidm.report(); 223 mUidm.report();
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index 73d611c04..1a5da411f 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -16,83 +16,118 @@
16 16
17#define LOG_TAG "storaged" 17#define LOG_TAG "storaged"
18 18
19#include <stdio.h>
19#include <string.h> 20#include <string.h>
20 21
21#include <android-base/file.h> 22#include <android-base/file.h>
22#include <android-base/logging.h>
23#include <android-base/parseint.h> 23#include <android-base/parseint.h>
24#include <android-base/logging.h>
24#include <log/log_event_list.h> 25#include <log/log_event_list.h>
25 26
26#include "storaged.h" 27#include "storaged.h"
27 28
28using namespace std; 29using namespace std;
29using namespace android;
30using namespace android::base; 30using namespace android::base;
31 31
32void storage_info_t::publish() 32void report_storage_health()
33{ 33{
34 if (eol == 0 && lifetime_a == 0 && lifetime_b == 0) { 34 emmc_info_t mmc;
35 return; 35 mmc.report();
36 } 36}
37 37
38void storage_info_t::publish()
39{
38 android_log_event_list(EVENTLOGTAG_EMMCINFO) 40 android_log_event_list(EVENTLOGTAG_EMMCINFO)
39 << version << eol << lifetime_a << lifetime_b 41 << version << eol << lifetime_a << lifetime_b
40 << LOG_ID_EVENTS; 42 << LOG_ID_EVENTS;
41} 43}
42 44
43bool emmc_info_t::init() 45bool emmc_info_t::report()
46{
47 if (!report_sysfs() && !report_debugfs())
48 return false;
49
50 publish();
51 return true;
52}
53
54bool emmc_info_t::report_sysfs()
44{ 55{
45 string buffer; 56 string buffer;
46 if (!ReadFileToString(ext_csd_file, &buffer) || 57 uint16_t rev = 0;
47 buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) { 58
59 if (!ReadFileToString(emmc_sysfs + "rev", &buffer)) {
48 return false; 60 return false;
49 } 61 }
50 62
51 string ver_str = buffer.substr(EXT_CSD_REV_IDX, sizeof(str_hex)); 63 if (sscanf(buffer.c_str(), "0x%hx", &rev) < 1 ||
52 uint8_t ext_csd_rev; 64 rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
53 if (!ParseUint(ver_str, &ext_csd_rev)) {
54 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV.";
55 return false; 65 return false;
56 } 66 }
57 67
58 version = "emmc "; 68 version = "emmc ";
59 version += (ext_csd_rev < ARRAY_SIZE(emmc_ver_str)) ? 69 version += emmc_ver_str[rev];
60 emmc_ver_str[ext_csd_rev] : "Unknown";
61 70
62 if (ext_csd_rev < 7) { 71 if (!ReadFileToString(emmc_sysfs + "pre_eol_info", &buffer)) {
63 return false; 72 return false;
64 } 73 }
65 74
66 return update(); 75 if (sscanf(buffer.c_str(), "%hx", &eol) < 1 || eol == 0) {
76 return false;
77 }
78
79 if (!ReadFileToString(emmc_sysfs + "life_time", &buffer)) {
80 return false;
81 }
82
83 if (sscanf(buffer.c_str(), "0x%hx 0x%hx", &lifetime_a, &lifetime_b) < 2 ||
84 (lifetime_a == 0 && lifetime_b == 0)) {
85 return false;
86 }
87
88 return true;
67} 89}
68 90
69bool emmc_info_t::update() 91const size_t EXT_CSD_FILE_MIN_SIZE = 1024;
92/* 2 characters in string for each byte */
93const size_t EXT_CSD_REV_IDX = 192 * 2;
94const size_t EXT_PRE_EOL_INFO_IDX = 267 * 2;
95const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * 2;
96const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * 2;
97
98bool emmc_info_t::report_debugfs()
70{ 99{
71 string buffer; 100 string buffer;
72 if (!ReadFileToString(ext_csd_file, &buffer) || 101 uint16_t rev = 0;
102
103 if (!ReadFileToString(emmc_debugfs, &buffer) ||
73 buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) { 104 buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
74 return false; 105 return false;
75 } 106 }
76 107
77 string str = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(str_hex)); 108 string str = buffer.substr(EXT_CSD_REV_IDX, 2);
109 if (!ParseUint(str, &rev) ||
110 rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
111 return false;
112 }
113
114 version = "emmc ";
115 version += emmc_ver_str[rev];
116
117 str = buffer.substr(EXT_PRE_EOL_INFO_IDX, 2);
78 if (!ParseUint(str, &eol)) { 118 if (!ParseUint(str, &eol)) {
79 LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO.";
80 return false; 119 return false;
81 } 120 }
82 121
83 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(str_hex)); 122 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, 2);
84 if (!ParseUint(str, &lifetime_a)) { 123 if (!ParseUint(str, &lifetime_a)) {
85 LOG_TO(SYSTEM, ERROR)
86 << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A.";
87 return false; 124 return false;
88 } 125 }
89 126
90 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(str_hex)); 127 str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, 2);
91 if (!ParseUint(str, &lifetime_b)) { 128 if (!ParseUint(str, &lifetime_b)) {
92 LOG_TO(SYSTEM, ERROR)
93 << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B.";
94 return false; 129 return false;
95 } 130 }
96 131
97 return true; 132 return true;
98} 133} \ No newline at end of file
diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp
index e335cad87..b103ac1ec 100644
--- a/storaged/tests/storaged_test.cpp
+++ b/storaged/tests/storaged_test.cpp
@@ -29,7 +29,6 @@
29 29
30#define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat" 30#define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat"
31#define SDA_DISK_STATS_PATH "/sys/block/sda/stat" 31#define SDA_DISK_STATS_PATH "/sys/block/sda/stat"
32#define EMMC_EXT_CSD_PATH "/d/mmc0/mmc0:0001/ext_csd"
33 32
34static void pause(uint32_t sec) { 33static void pause(uint32_t sec) {
35 const char* path = "/cache/test"; 34 const char* path = "/cache/test";
@@ -58,13 +57,8 @@ static void pause(uint32_t sec) {
58const char* DISK_STATS_PATH; 57const char* DISK_STATS_PATH;
59TEST(storaged_test, retvals) { 58TEST(storaged_test, retvals) {
60 struct disk_stats stats; 59 struct disk_stats stats;
61 emmc_info_t info;
62 memset(&stats, 0, sizeof(struct disk_stats)); 60 memset(&stats, 0, sizeof(struct disk_stats));
63 61
64 if (info.init()) {
65 EXPECT_TRUE(info.update());
66 }
67
68 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) { 62 if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
69 DISK_STATS_PATH = MMC_DISK_STATS_PATH; 63 DISK_STATS_PATH = MMC_DISK_STATS_PATH;
70 } else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) { 64 } else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) {
@@ -127,20 +121,6 @@ TEST(storaged_test, disk_stats) {
127 } 121 }
128} 122}
129 123
130TEST(storaged_test, storage_info_t) {
131 emmc_info_t info;
132
133 if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) {
134 int ret = info.init();
135 if (ret) {
136 EXPECT_TRUE(info.version.empty());
137 ASSERT_TRUE(info.update());
138 // update should put something in info.
139 EXPECT_TRUE(info.eol || info.lifetime_a || info.lifetime_b);
140 }
141 }
142}
143
144static double mean(std::deque<uint32_t> nums) { 124static double mean(std::deque<uint32_t> nums) {
145 double sum = 0.0; 125 double sum = 0.0;
146 for (uint32_t i : nums) { 126 for (uint32_t i : nums) {