blob: 06afea693c26fa7f00b96a5185805b26d81cbd29 [file] [log] [blame]
ynwang62cb3722016-06-17 14:30:48 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "storaged"
18
19#include <stdlib.h>
20#include <time.h>
21#include <unistd.h>
22
ynwang62cb3722016-06-17 14:30:48 -070023#include <android-base/logging.h>
Jin Qian5b962c62017-01-30 14:48:38 -080024#include <batteryservice/BatteryServiceConstants.h>
25#include <batteryservice/IBatteryPropertiesRegistrar.h>
Jin Qian26b2be02017-04-03 18:10:38 -070026#include <binder/IPCThreadState.h>
Jin Qian5b962c62017-01-30 14:48:38 -080027#include <binder/IServiceManager.h>
Jin Qian3790f5b2017-01-23 14:38:47 -080028#include <cutils/properties.h>
Jin Qianf42d7c82017-01-26 11:20:26 -080029#include <log/log.h>
ynwang62cb3722016-06-17 14:30:48 -070030
31#include <storaged.h>
32#include <storaged_utils.h>
33
34/* disk_stats_publisher */
35void disk_stats_publisher::publish(void) {
36 // Logging
ynwang62cb3722016-06-17 14:30:48 -070037 struct disk_perf perf = get_disk_perf(&mAccumulate);
Jin Qian27506fa2017-01-17 11:51:51 -080038 log_debug_disk_perf(&perf, "regular");
ynwang62cb3722016-06-17 14:30:48 -070039 log_event_disk_stats(&mAccumulate, "regular");
40 // Reset global structures
41 memset(&mAccumulate, 0, sizeof(struct disk_stats));
42}
43
44void disk_stats_publisher::update(void) {
45 struct disk_stats curr;
46 if (parse_disk_stats(DISK_STATS_PATH, &curr)) {
47 struct disk_stats inc = get_inc_disk_stats(&mPrevious, &curr);
48 add_disk_stats(&inc, &mAccumulate);
ynwangaf49d972016-06-17 14:30:48 -070049#ifdef DEBUG
ynwang62cb3722016-06-17 14:30:48 -070050// log_kernel_disk_stats(&mPrevious, "prev stats");
51// log_kernel_disk_stats(&curr, "curr stats");
52// log_kernel_disk_stats(&inc, "inc stats");
53// log_kernel_disk_stats(&mAccumulate, "accumulated stats");
ynwangaf49d972016-06-17 14:30:48 -070054#endif
ynwang62cb3722016-06-17 14:30:48 -070055 mPrevious = curr;
56 }
57}
58
59/* disk_stats_monitor */
60void disk_stats_monitor::update_mean() {
61 CHECK(mValid);
62 mMean.read_perf = (uint32_t)mStats.read_perf.get_mean();
63 mMean.read_ios = (uint32_t)mStats.read_ios.get_mean();
64 mMean.write_perf = (uint32_t)mStats.write_perf.get_mean();
65 mMean.write_ios = (uint32_t)mStats.write_ios.get_mean();
66 mMean.queue = (uint32_t)mStats.queue.get_mean();
67}
68
69void disk_stats_monitor::update_std() {
70 CHECK(mValid);
71 mStd.read_perf = (uint32_t)mStats.read_perf.get_std();
72 mStd.read_ios = (uint32_t)mStats.read_ios.get_std();
73 mStd.write_perf = (uint32_t)mStats.write_perf.get_std();
74 mStd.write_ios = (uint32_t)mStats.write_ios.get_std();
75 mStd.queue = (uint32_t)mStats.queue.get_std();
76}
77
78void disk_stats_monitor::add(struct disk_perf* perf) {
79 mStats.read_perf.add(perf->read_perf);
80 mStats.read_ios.add(perf->read_ios);
81 mStats.write_perf.add(perf->write_perf);
82 mStats.write_ios.add(perf->write_ios);
83 mStats.queue.add(perf->queue);
84}
85
86void disk_stats_monitor::evict(struct disk_perf* perf) {
87 mStats.read_perf.evict(perf->read_perf);
88 mStats.read_ios.evict(perf->read_ios);
89 mStats.write_perf.evict(perf->write_perf);
90 mStats.write_ios.evict(perf->write_ios);
91 mStats.queue.evict(perf->queue);
92}
93
94bool disk_stats_monitor::detect(struct disk_perf* perf) {
95 return ((double)perf->queue >= (double)mMean.queue + mSigma * (double)mStd.queue) &&
96 ((double)perf->read_perf < (double)mMean.read_perf - mSigma * (double)mStd.read_perf) &&
97 ((double)perf->write_perf < (double)mMean.write_perf - mSigma * (double)mStd.write_perf);
98}
99
100void disk_stats_monitor::update(struct disk_stats* stats) {
101 struct disk_stats inc = get_inc_disk_stats(&mPrevious, stats);
102 struct disk_perf perf = get_disk_perf(&inc);
103 // Update internal data structures
104 if (LIKELY(mValid)) {
105 CHECK_EQ(mBuffer.size(), mWindow);
106
107 if (UNLIKELY(detect(&perf))) {
108 mStall = true;
109 add_disk_stats(&inc, &mAccumulate);
Jin Qian27506fa2017-01-17 11:51:51 -0800110 log_debug_disk_perf(&mMean, "stalled_mean");
111 log_debug_disk_perf(&mStd, "stalled_std");
ynwang62cb3722016-06-17 14:30:48 -0700112 } else {
113 if (mStall) {
ynwang62cb3722016-06-17 14:30:48 -0700114 struct disk_perf acc_perf = get_disk_perf(&mAccumulate);
Jin Qian27506fa2017-01-17 11:51:51 -0800115 log_debug_disk_perf(&acc_perf, "stalled");
ynwang62cb3722016-06-17 14:30:48 -0700116 log_event_disk_stats(&mAccumulate, "stalled");
117 mStall = false;
118 memset(&mAccumulate, 0, sizeof(mAccumulate));
119 }
120 }
121
122 evict(&mBuffer.front());
123 mBuffer.pop();
124 add(&perf);
125 mBuffer.push(perf);
126
127 update_mean();
128 update_std();
129
130 } else { /* mValid == false */
131 CHECK_LT(mBuffer.size(), mWindow);
132 add(&perf);
133 mBuffer.push(perf);
134 if (mBuffer.size() == mWindow) {
135 mValid = true;
136 update_mean();
137 update_std();
138 }
139 }
140
141 mPrevious = *stats;
142}
143
144void disk_stats_monitor::update(void) {
145 struct disk_stats curr;
146 if (LIKELY(parse_disk_stats(DISK_STATS_PATH, &curr))) {
147 update(&curr);
148 }
149}
150
Jin Qian5b962c62017-01-30 14:48:38 -0800151static sp<IBatteryPropertiesRegistrar> get_battery_properties_service() {
152 sp<IServiceManager> sm = defaultServiceManager();
153 if (sm == NULL) return NULL;
154
155 sp<IBinder> binder = sm->getService(String16("batteryproperties"));
156 if (binder == NULL) return NULL;
157
158 sp<IBatteryPropertiesRegistrar> battery_properties =
159 interface_cast<IBatteryPropertiesRegistrar>(binder);
160
161 return battery_properties;
162}
163
164static inline charger_stat_t is_charger_on(int64_t prop) {
165 return (prop == BATTERY_STATUS_CHARGING || prop == BATTERY_STATUS_FULL) ?
166 CHARGER_ON : CHARGER_OFF;
167}
168
169void storaged_t::batteryPropertiesChanged(struct BatteryProperties props) {
170 mUidm.set_charger_state(is_charger_on(props.batteryStatus));
171}
172
173void storaged_t::init_battery_service() {
Jin Qianba27df42017-03-28 15:21:20 -0700174 if (!mConfig.proc_uid_io_available)
175 return;
176
Jin Qian566e63d2017-03-31 14:26:23 -0700177 battery_properties = get_battery_properties_service();
Jin Qian5b962c62017-01-30 14:48:38 -0800178 if (battery_properties == NULL) {
179 LOG_TO(SYSTEM, WARNING) << "failed to find batteryproperties service";
180 return;
181 }
182
183 struct BatteryProperty val;
184 battery_properties->getProperty(BATTERY_PROP_BATTERY_STATUS, &val);
185 mUidm.init(is_charger_on(val.valueInt64));
186
187 // register listener after init uid_monitor
188 battery_properties->registerListener(this);
Jin Qian566e63d2017-03-31 14:26:23 -0700189 IInterface::asBinder(battery_properties)->linkToDeath(this);
190}
191
192void storaged_t::binderDied(const wp<IBinder>& who) {
193 if (battery_properties != NULL &&
194 IInterface::asBinder(battery_properties) == who) {
195 LOG_TO(SYSTEM, ERROR) << "batteryproperties service died, exiting";
Jin Qian26b2be02017-04-03 18:10:38 -0700196 IPCThreadState::self()->stopProcess();
Jin Qian566e63d2017-03-31 14:26:23 -0700197 exit(1);
198 } else {
199 LOG_TO(SYSTEM, ERROR) << "unknown service died";
200 }
Jin Qian5b962c62017-01-30 14:48:38 -0800201}
202
Jin Qian8847c622017-07-17 15:06:11 -0700203void storaged_t::report_storage_info() {
204 storage_info->report();
205}
206
ynwang62cb3722016-06-17 14:30:48 -0700207/* storaged_t */
208storaged_t::storaged_t(void) {
ynwang62cb3722016-06-17 14:30:48 -0700209 if (access(MMC_DISK_STATS_PATH, R_OK) < 0 && access(SDA_DISK_STATS_PATH, R_OK) < 0) {
210 mConfig.diskstats_available = false;
211 } else {
212 mConfig.diskstats_available = true;
213 }
214
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800215 mConfig.proc_uid_io_available = (access(UID_IO_STATS_PATH, R_OK) == 0);
216
Jin Qian3790f5b2017-01-23 14:38:47 -0800217 mConfig.periodic_chores_interval_unit =
218 property_get_int32("ro.storaged.event.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT);
219
220 mConfig.event_time_check_usec =
221 property_get_int32("ro.storaged.event.perf_check", 0);
222
223 mConfig.periodic_chores_interval_disk_stats_publish =
224 property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH);
225
Jin Qian5b962c62017-01-30 14:48:38 -0800226 mConfig.periodic_chores_interval_uid_io =
227 property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
ynwang62cb3722016-06-17 14:30:48 -0700228
Jin Qian8847c622017-07-17 15:06:11 -0700229 storage_info.reset(storage_info_t::get_storage_info());
230
ynwang62cb3722016-06-17 14:30:48 -0700231 mStarttime = time(NULL);
232}
233
234void storaged_t::event(void) {
235 if (mConfig.diskstats_available) {
236 mDiskStats.update();
237 mDsm.update();
Jin Qian8847c622017-07-17 15:06:11 -0700238 storage_info->refresh();
ynwang62cb3722016-06-17 14:30:48 -0700239 if (mTimer && (mTimer % mConfig.periodic_chores_interval_disk_stats_publish) == 0) {
240 mDiskStats.publish();
241 }
242 }
243
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800244 if (mConfig.proc_uid_io_available && mTimer &&
Jin Qian5b962c62017-01-30 14:48:38 -0800245 (mTimer % mConfig.periodic_chores_interval_uid_io) == 0) {
Jin Qianbcd6e3b2016-12-28 15:43:51 -0800246 mUidm.report();
247 }
248
ynwang62cb3722016-06-17 14:30:48 -0700249 mTimer += mConfig.periodic_chores_interval_unit;
ynwangaf49d972016-06-17 14:30:48 -0700250}
Jin Qian3790f5b2017-01-23 14:38:47 -0800251
252void storaged_t::event_checked(void) {
253 struct timespec start_ts, end_ts;
254 bool check_time = true;
255
256 if (mConfig.event_time_check_usec &&
257 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_ts) < 0) {
258 check_time = false;
Jin Qianf42d7c82017-01-26 11:20:26 -0800259 static time_t state_a;
260 IF_ALOG_RATELIMIT_LOCAL(300, &state_a) {
261 PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
262 }
Jin Qian3790f5b2017-01-23 14:38:47 -0800263 }
264
265 event();
266
Jin Qianf42d7c82017-01-26 11:20:26 -0800267 if (mConfig.event_time_check_usec && check_time) {
Jin Qian3790f5b2017-01-23 14:38:47 -0800268 if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_ts) < 0) {
Jin Qianf42d7c82017-01-26 11:20:26 -0800269 static time_t state_b;
270 IF_ALOG_RATELIMIT_LOCAL(300, &state_b) {
271 PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed";
272 }
Jin Qian3790f5b2017-01-23 14:38:47 -0800273 return;
274 }
275 int64_t cost = (end_ts.tv_sec - start_ts.tv_sec) * SEC_TO_USEC +
276 (end_ts.tv_nsec - start_ts.tv_nsec) / USEC_TO_NSEC;
277 if (cost > mConfig.event_time_check_usec) {
278 LOG_TO(SYSTEM, ERROR)
279 << "event loop spent " << cost << " usec, threshold "
280 << mConfig.event_time_check_usec << " usec";
281 }
282 }
283}