ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 1 | /* |
| 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 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 19 | #include <dirent.h> |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 20 | #include <stdlib.h> |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 21 | #include <stdio.h> |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 22 | #include <time.h> |
| 23 | #include <unistd.h> |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 24 | #include <zlib.h> |
| 25 | |
| 26 | #include <chrono> |
| 27 | #include <fstream> |
| 28 | #include <sstream> |
| 29 | #include <string> |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 30 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 31 | #include <android-base/file.h> |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 32 | #include <android-base/logging.h> |
Yifan Hong | 70c44e7 | 2018-01-16 17:50:58 -0800 | [diff] [blame] | 33 | #include <android/hidl/manager/1.0/IServiceManager.h> |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 34 | #include <batteryservice/BatteryServiceConstants.h> |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 35 | #include <cutils/properties.h> |
Yifan Hong | 70c44e7 | 2018-01-16 17:50:58 -0800 | [diff] [blame] | 36 | #include <healthhalutils/HealthHalUtils.h> |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 37 | #include <hidl/HidlTransportSupport.h> |
| 38 | #include <hwbinder/IPCThreadState.h> |
Jin Qian | f42d7c8 | 2017-01-26 11:20:26 -0800 | [diff] [blame] | 39 | #include <log/log.h> |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 40 | |
| 41 | #include <storaged.h> |
| 42 | #include <storaged_utils.h> |
| 43 | |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 44 | using namespace android::base; |
| 45 | using namespace chrono; |
| 46 | using namespace google::protobuf::io; |
| 47 | using namespace storaged_proto; |
| 48 | |
| 49 | namespace { |
| 50 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 51 | /* |
| 52 | * The system user is the initial user that is implicitly created on first boot |
| 53 | * and hosts most of the system services. Keep this in sync with |
| 54 | * frameworks/base/core/java/android/os/UserManager.java |
| 55 | */ |
| 56 | constexpr int USER_SYSTEM = 0; |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 57 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 58 | constexpr ssize_t benchmark_unit_size = 16 * 1024; // 16KB |
| 59 | |
| 60 | constexpr ssize_t min_benchmark_size = 128 * 1024; // 128KB |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 61 | |
| 62 | } // namespace |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 63 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 64 | const uint32_t storaged_t::current_version = 4; |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 65 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 66 | using android::hardware::interfacesEqual; |
| 67 | using android::hardware::Return; |
Yifan Hong | 70c44e7 | 2018-01-16 17:50:58 -0800 | [diff] [blame] | 68 | using android::hardware::health::V1_0::BatteryStatus; |
Yifan Hong | 70c44e7 | 2018-01-16 17:50:58 -0800 | [diff] [blame] | 69 | using android::hardware::health::V1_0::toString; |
| 70 | using android::hardware::health::V2_0::get_health_service; |
Hridya Valsaraju | 79d38eb | 2018-01-17 23:02:56 -0800 | [diff] [blame] | 71 | using android::hardware::health::V2_0::HealthInfo; |
Yifan Hong | 70c44e7 | 2018-01-16 17:50:58 -0800 | [diff] [blame] | 72 | using android::hardware::health::V2_0::IHealth; |
| 73 | using android::hardware::health::V2_0::Result; |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 74 | using android::hidl::manager::V1_0::IServiceManager; |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 75 | |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 76 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 77 | inline charger_stat_t is_charger_on(BatteryStatus prop) { |
| 78 | return (prop == BatteryStatus::CHARGING || prop == BatteryStatus::FULL) ? |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 79 | CHARGER_ON : CHARGER_OFF; |
| 80 | } |
| 81 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 82 | Return<void> storaged_t::healthInfoChanged(const HealthInfo& props) { |
Hridya Valsaraju | 79d38eb | 2018-01-17 23:02:56 -0800 | [diff] [blame] | 83 | mUidm.set_charger_state(is_charger_on(props.legacy.batteryStatus)); |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 84 | return android::hardware::Void(); |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 85 | } |
| 86 | |
Yifan Hong | 4a43bdc | 2018-01-16 17:20:32 -0800 | [diff] [blame] | 87 | void storaged_t::init() { |
| 88 | init_health_service(); |
Yifan Hong | c4b46e0 | 2018-01-16 15:49:08 -0800 | [diff] [blame] | 89 | mDsm = std::make_unique<disk_stats_monitor>(health); |
Yifan Hong | 845e35b | 2018-01-16 16:03:36 -0800 | [diff] [blame] | 90 | storage_info.reset(storage_info_t::get_storage_info(health)); |
Yifan Hong | 4a43bdc | 2018-01-16 17:20:32 -0800 | [diff] [blame] | 91 | } |
| 92 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 93 | void storaged_t::init_health_service() { |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 94 | if (!mUidm.enabled()) |
Jin Qian | ba27df4 | 2017-03-28 15:21:20 -0700 | [diff] [blame] | 95 | return; |
| 96 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 97 | health = get_health_service(); |
| 98 | if (health == NULL) { |
| 99 | LOG_TO(SYSTEM, WARNING) << "health: failed to find IHealth service"; |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 100 | return; |
| 101 | } |
| 102 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 103 | BatteryStatus status = BatteryStatus::UNKNOWN; |
| 104 | auto ret = health->getChargeStatus([&](Result r, BatteryStatus v) { |
| 105 | if (r != Result::SUCCESS) { |
| 106 | LOG_TO(SYSTEM, WARNING) |
| 107 | << "health: cannot get battery status " << toString(r); |
| 108 | return; |
| 109 | } |
| 110 | if (v == BatteryStatus::UNKNOWN) { |
| 111 | LOG_TO(SYSTEM, WARNING) << "health: invalid battery status"; |
| 112 | } |
| 113 | status = v; |
| 114 | }); |
| 115 | if (!ret.isOk()) { |
| 116 | LOG_TO(SYSTEM, WARNING) << "health: get charge status transaction error " |
| 117 | << ret.description(); |
| 118 | } |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 119 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 120 | mUidm.init(is_charger_on(status)); |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 121 | // register listener after init uid_monitor |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 122 | health->registerCallback(this); |
| 123 | health->linkToDeath(this, 0 /* cookie */); |
Jin Qian | 566e63d | 2017-03-31 14:26:23 -0700 | [diff] [blame] | 124 | } |
| 125 | |
Yifan Hong | bf2dcb2 | 2017-09-27 14:01:30 -0700 | [diff] [blame] | 126 | void storaged_t::serviceDied(uint64_t cookie, const wp<::android::hidl::base::V1_0::IBase>& who) { |
| 127 | if (health != NULL && interfacesEqual(health, who.promote())) { |
| 128 | LOG_TO(SYSTEM, ERROR) << "health service died, exiting"; |
| 129 | android::hardware::IPCThreadState::self()->stopProcess(); |
Jin Qian | 566e63d | 2017-03-31 14:26:23 -0700 | [diff] [blame] | 130 | exit(1); |
| 131 | } else { |
| 132 | LOG_TO(SYSTEM, ERROR) << "unknown service died"; |
| 133 | } |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 134 | } |
| 135 | |
Jin Qian | 8847c62 | 2017-07-17 15:06:11 -0700 | [diff] [blame] | 136 | void storaged_t::report_storage_info() { |
| 137 | storage_info->report(); |
| 138 | } |
| 139 | |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 140 | /* storaged_t */ |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 141 | storaged_t::storaged_t(void) { |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 142 | mConfig.periodic_chores_interval_unit = |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 143 | property_get_int32("ro.storaged.event.interval", |
| 144 | DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT); |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 145 | |
| 146 | mConfig.event_time_check_usec = |
| 147 | property_get_int32("ro.storaged.event.perf_check", 0); |
| 148 | |
| 149 | mConfig.periodic_chores_interval_disk_stats_publish = |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 150 | property_get_int32("ro.storaged.disk_stats_pub", |
| 151 | DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH); |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 152 | |
Jin Qian | 5b962c6 | 2017-01-30 14:48:38 -0800 | [diff] [blame] | 153 | mConfig.periodic_chores_interval_uid_io = |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 154 | property_get_int32("ro.storaged.uid_io.interval", |
| 155 | DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO); |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 156 | |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 157 | mConfig.periodic_chores_interval_flush_proto = |
| 158 | property_get_int32("ro.storaged.flush_proto.interval", |
| 159 | DEFAULT_PERIODIC_CHORES_INTERVAL_FLUSH_PROTO); |
| 160 | |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 161 | mStarttime = time(NULL); |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 162 | mTimer = 0; |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 163 | } |
| 164 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 165 | void storaged_t::add_user_ce(userid_t user_id) { |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 166 | load_proto(user_id); |
| 167 | proto_loaded[user_id] = true; |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 168 | } |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 169 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 170 | void storaged_t::remove_user_ce(userid_t user_id) { |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 171 | proto_loaded[user_id] = false; |
| 172 | mUidm.clear_user_history(user_id); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 173 | RemoveFileIfExists(proto_path(user_id), nullptr); |
| 174 | } |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 175 | |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 176 | void storaged_t::load_proto(userid_t user_id) { |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 177 | string proto_file = proto_path(user_id); |
| 178 | ifstream in(proto_file, ofstream::in | ofstream::binary); |
| 179 | |
| 180 | if (!in.good()) return; |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 181 | |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 182 | stringstream ss; |
| 183 | ss << in.rdbuf(); |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 184 | StoragedProto proto; |
| 185 | proto.ParseFromString(ss.str()); |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 186 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 187 | const UidIOUsage& uid_io_usage = proto.uid_io_usage(); |
| 188 | uint32_t computed_crc = crc32(current_version, |
| 189 | reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), |
| 190 | uid_io_usage.ByteSize()); |
| 191 | if (proto.crc() != computed_crc) { |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 192 | LOG_TO(SYSTEM, WARNING) << "CRC mismatch in " << proto_file; |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 193 | return; |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 194 | } |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 195 | |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 196 | mUidm.load_uid_io_proto(proto.uid_io_usage()); |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 197 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 198 | if (user_id == USER_SYSTEM) { |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 199 | storage_info->load_perf_history_proto(proto.perf_history()); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 200 | } |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 201 | } |
| 202 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 203 | char* storaged_t:: prepare_proto(userid_t user_id, StoragedProto* proto) { |
| 204 | proto->set_version(current_version); |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 205 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 206 | const UidIOUsage& uid_io_usage = proto->uid_io_usage(); |
| 207 | proto->set_crc(crc32(current_version, |
| 208 | reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), |
| 209 | uid_io_usage.ByteSize())); |
| 210 | |
| 211 | uint32_t pagesize = sysconf(_SC_PAGESIZE); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 212 | if (user_id == USER_SYSTEM) { |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 213 | proto->set_padding("", 1); |
| 214 | vector<char> padding; |
| 215 | ssize_t size = ROUND_UP(MAX(min_benchmark_size, proto->ByteSize()), |
| 216 | pagesize); |
| 217 | padding = vector<char>(size - proto->ByteSize(), 0xFD); |
| 218 | proto->set_padding(padding.data(), padding.size()); |
| 219 | while (!IS_ALIGNED(proto->ByteSize(), pagesize)) { |
| 220 | padding.push_back(0xFD); |
| 221 | proto->set_padding(padding.data(), padding.size()); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 222 | } |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 223 | } |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 224 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 225 | char* data = nullptr; |
| 226 | if (posix_memalign(reinterpret_cast<void**>(&data), |
| 227 | pagesize, proto->ByteSize())) { |
| 228 | PLOG_TO(SYSTEM, ERROR) << "Faied to alloc aligned buffer (size: " |
| 229 | << proto->ByteSize() << ")"; |
| 230 | return data; |
| 231 | } |
| 232 | |
| 233 | proto->SerializeToArray(data, proto->ByteSize()); |
| 234 | return data; |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 235 | } |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 236 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 237 | void storaged_t::flush_proto_data(userid_t user_id, |
| 238 | const char* data, ssize_t size) { |
| 239 | string proto_file = proto_path(user_id); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 240 | string tmp_file = proto_file + "_tmp"; |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 241 | unique_fd fd(TEMP_FAILURE_RETRY(open(tmp_file.c_str(), |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 242 | O_SYNC | O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC | |
| 243 | (user_id == USER_SYSTEM ? O_DIRECT : 0), |
| 244 | S_IRUSR | S_IWUSR))); |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 245 | if (fd == -1) { |
| 246 | PLOG_TO(SYSTEM, ERROR) << "Faied to open tmp file: " << tmp_file; |
| 247 | return; |
| 248 | } |
| 249 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 250 | if (user_id == USER_SYSTEM) { |
| 251 | time_point<steady_clock> start, end; |
| 252 | uint32_t benchmark_size = 0; |
| 253 | uint64_t benchmark_time_ns = 0; |
| 254 | ssize_t ret; |
| 255 | bool first_write = true; |
| 256 | |
| 257 | while (size > 0) { |
| 258 | start = steady_clock::now(); |
| 259 | ret = write(fd, data, MIN(benchmark_unit_size, size)); |
| 260 | if (ret <= 0) { |
| 261 | PLOG_TO(SYSTEM, ERROR) << "Faied to write tmp file: " << tmp_file; |
| 262 | return; |
| 263 | } |
| 264 | end = steady_clock::now(); |
| 265 | /* |
| 266 | * compute bandwidth after the first write and if write returns |
| 267 | * exactly unit size. |
| 268 | */ |
| 269 | if (!first_write && ret == benchmark_unit_size) { |
| 270 | benchmark_size += benchmark_unit_size; |
| 271 | benchmark_time_ns += duration_cast<nanoseconds>(end - start).count(); |
| 272 | } |
| 273 | size -= ret; |
| 274 | data += ret; |
| 275 | first_write = false; |
| 276 | } |
| 277 | |
| 278 | if (benchmark_size) { |
| 279 | int perf = benchmark_size * 1000000LLU / benchmark_time_ns; |
| 280 | storage_info->update_perf_history(perf, system_clock::now()); |
| 281 | } |
| 282 | } else { |
| 283 | if (!WriteFully(fd, data, size)) { |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 284 | PLOG_TO(SYSTEM, ERROR) << "Faied to write tmp file: " << tmp_file; |
| 285 | return; |
| 286 | } |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 287 | } |
| 288 | |
| 289 | fd.reset(-1); |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 290 | rename(tmp_file.c_str(), proto_file.c_str()); |
| 291 | } |
| 292 | |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 293 | void storaged_t::flush_proto(userid_t user_id, StoragedProto* proto) { |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 294 | unique_ptr<char> proto_data(prepare_proto(user_id, proto)); |
| 295 | if (proto_data == nullptr) return; |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 296 | |
Jin Qian | 4c23c45 | 2017-12-12 18:38:25 -0800 | [diff] [blame] | 297 | flush_proto_data(user_id, proto_data.get(), proto->ByteSize()); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 298 | } |
| 299 | |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 300 | void storaged_t::flush_protos(unordered_map<int, StoragedProto>* protos) { |
| 301 | for (auto& it : *protos) { |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 302 | /* |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 303 | * Don't flush proto if we haven't attempted to load it from file. |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 304 | */ |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 305 | if (proto_loaded[it.first]) { |
| 306 | flush_proto(it.first, &it.second); |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 307 | } |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 308 | } |
| 309 | } |
| 310 | |
| 311 | void storaged_t::event(void) { |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 312 | unordered_map<int, StoragedProto> protos; |
| 313 | |
Yifan Hong | c4b46e0 | 2018-01-16 15:49:08 -0800 | [diff] [blame] | 314 | if (mDsm->enabled()) { |
| 315 | mDsm->update(); |
Jin Qian | 65dea71 | 2017-08-29 16:48:20 -0700 | [diff] [blame] | 316 | if (!(mTimer % mConfig.periodic_chores_interval_disk_stats_publish)) { |
Yifan Hong | c4b46e0 | 2018-01-16 15:49:08 -0800 | [diff] [blame] | 317 | mDsm->publish(); |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 318 | } |
| 319 | } |
| 320 | |
Jin Qian | a853332 | 2017-10-13 18:15:34 -0700 | [diff] [blame] | 321 | if (!(mTimer % mConfig.periodic_chores_interval_uid_io)) { |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 322 | mUidm.report(&protos); |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 323 | } |
| 324 | |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 325 | if (storage_info) { |
Jin Qian | 6df3bc6 | 2017-10-18 17:52:14 -0700 | [diff] [blame] | 326 | storage_info->refresh(protos[USER_SYSTEM].mutable_perf_history()); |
| 327 | } |
| 328 | |
Jin Qian | d691d6e | 2017-09-28 16:02:22 -0700 | [diff] [blame] | 329 | if (!(mTimer % mConfig.periodic_chores_interval_flush_proto)) { |
Jin Qian | 94b64ef | 2017-11-09 15:07:18 -0800 | [diff] [blame] | 330 | flush_protos(&protos); |
Jin Qian | bcd6e3b | 2016-12-28 15:43:51 -0800 | [diff] [blame] | 331 | } |
| 332 | |
ynwang | 62cb372 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 333 | mTimer += mConfig.periodic_chores_interval_unit; |
ynwang | af49d97 | 2016-06-17 14:30:48 -0700 | [diff] [blame] | 334 | } |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 335 | |
| 336 | void storaged_t::event_checked(void) { |
| 337 | struct timespec start_ts, end_ts; |
| 338 | bool check_time = true; |
| 339 | |
| 340 | if (mConfig.event_time_check_usec && |
| 341 | clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_ts) < 0) { |
| 342 | check_time = false; |
Jin Qian | f42d7c8 | 2017-01-26 11:20:26 -0800 | [diff] [blame] | 343 | static time_t state_a; |
| 344 | IF_ALOG_RATELIMIT_LOCAL(300, &state_a) { |
| 345 | PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed"; |
| 346 | } |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 347 | } |
| 348 | |
| 349 | event(); |
| 350 | |
Jin Qian | f42d7c8 | 2017-01-26 11:20:26 -0800 | [diff] [blame] | 351 | if (mConfig.event_time_check_usec && check_time) { |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 352 | if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_ts) < 0) { |
Jin Qian | f42d7c8 | 2017-01-26 11:20:26 -0800 | [diff] [blame] | 353 | static time_t state_b; |
| 354 | IF_ALOG_RATELIMIT_LOCAL(300, &state_b) { |
| 355 | PLOG_TO(SYSTEM, ERROR) << "clock_gettime() failed"; |
| 356 | } |
Jin Qian | 3790f5b | 2017-01-23 14:38:47 -0800 | [diff] [blame] | 357 | return; |
| 358 | } |
| 359 | int64_t cost = (end_ts.tv_sec - start_ts.tv_sec) * SEC_TO_USEC + |
| 360 | (end_ts.tv_nsec - start_ts.tv_nsec) / USEC_TO_NSEC; |
| 361 | if (cost > mConfig.event_time_check_usec) { |
| 362 | LOG_TO(SYSTEM, ERROR) |
| 363 | << "event loop spent " << cost << " usec, threshold " |
| 364 | << mConfig.event_time_check_usec << " usec"; |
| 365 | } |
| 366 | } |
| 367 | } |