summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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) {