Loading storaged/include/storaged.h +6 −3 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ friend class test_case_name##_##test_name##_Test #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define IS_ALIGNED(x, align) (!((x) & ((align) - 1))) #define ROUND_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) #define SECTOR_SIZE ( 512 ) #define SEC_TO_MSEC ( 1000 ) #define MSEC_TO_USEC ( 1000 ) Loading Loading @@ -83,12 +86,12 @@ class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback, time_t mStarttime; sp<android::hardware::health::V2_0::IHealth> health; unique_ptr<storage_info_t> storage_info; static const uint32_t crc_init; static const uint32_t current_version; unordered_map<userid_t, bool> proto_loaded; void load_proto(userid_t user_id); void prepare_proto(userid_t user_id, StoragedProto* proto); char* prepare_proto(userid_t user_id, StoragedProto* proto); void flush_proto(userid_t user_id, StoragedProto* proto); void flush_proto_user_system(StoragedProto* proto); void flush_proto_data(userid_t user_id, const char* data, ssize_t size); string proto_path(userid_t user_id) { return string("/data/misc_ce/") + to_string(user_id) + "/storaged/storaged.proto"; Loading storaged/storaged.cpp +79 −67 Original line number Diff line number Diff line Loading @@ -54,11 +54,13 @@ namespace { */ constexpr int USER_SYSTEM = 0; constexpr uint32_t benchmark_unit_size = 16 * 1024; // 16KB constexpr ssize_t benchmark_unit_size = 16 * 1024; // 16KB constexpr ssize_t min_benchmark_size = 128 * 1024; // 128KB } // namespace const uint32_t storaged_t::crc_init = 0x5108A4ED; /* STORAGED */ const uint32_t storaged_t::current_version = 4; using android::hardware::health::V1_0::BatteryStatus; using android::hardware::health::V1_0::toString; Loading Loading @@ -186,14 +188,11 @@ void storaged_t::load_proto(userid_t user_id) { StoragedProto proto; proto.ParseFromString(ss.str()); uint32_t crc = proto.crc(); proto.set_crc(crc_init); string proto_str = proto.SerializeAsString(); uint32_t computed_crc = crc32(crc_init, reinterpret_cast<const Bytef*>(proto_str.c_str()), proto_str.size()); if (crc != computed_crc) { const UidIOUsage& uid_io_usage = proto.uid_io_usage(); uint32_t computed_crc = crc32(current_version, reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), uid_io_usage.ByteSize()); if (proto.crc() != computed_crc) { LOG_TO(SYSTEM, WARNING) << "CRC mismatch in " << proto_file; return; } Loading @@ -205,41 +204,60 @@ void storaged_t::load_proto(userid_t user_id) { } } void storaged_t:: prepare_proto(userid_t user_id, StoragedProto* proto) { proto->set_version(3); proto->set_crc(crc_init); char* storaged_t:: prepare_proto(userid_t user_id, StoragedProto* proto) { proto->set_version(current_version); const UidIOUsage& uid_io_usage = proto->uid_io_usage(); proto->set_crc(crc32(current_version, reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), uid_io_usage.ByteSize())); uint32_t pagesize = sysconf(_SC_PAGESIZE); if (user_id == USER_SYSTEM) { while (proto->ByteSize() < 128 * 1024) { proto->add_padding(0xFEEDBABE); proto->set_padding("", 1); vector<char> padding; ssize_t size = ROUND_UP(MAX(min_benchmark_size, proto->ByteSize()), pagesize); padding = vector<char>(size - proto->ByteSize(), 0xFD); proto->set_padding(padding.data(), padding.size()); while (!IS_ALIGNED(proto->ByteSize(), pagesize)) { padding.push_back(0xFD); proto->set_padding(padding.data(), padding.size()); } } string proto_str = proto->SerializeAsString(); proto->set_crc(crc32(crc_init, reinterpret_cast<const Bytef*>(proto_str.c_str()), proto_str.size())); char* data = nullptr; if (posix_memalign(reinterpret_cast<void**>(&data), pagesize, proto->ByteSize())) { PLOG_TO(SYSTEM, ERROR) << "Faied to alloc aligned buffer (size: " << proto->ByteSize() << ")"; return data; } void storaged_t::flush_proto_user_system(StoragedProto* proto) { string proto_str = proto->SerializeAsString(); const char* data = proto_str.data(); uint32_t size = proto_str.size(); ssize_t ret; time_point<steady_clock> start, end; proto->SerializeToArray(data, proto->ByteSize()); return data; } string proto_file = proto_path(USER_SYSTEM); void storaged_t::flush_proto_data(userid_t user_id, const char* data, ssize_t size) { string proto_file = proto_path(user_id); string tmp_file = proto_file + "_tmp"; unique_fd fd(TEMP_FAILURE_RETRY(open(tmp_file.c_str(), O_DIRECT | O_SYNC | O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, O_SYNC | O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC | (user_id == USER_SYSTEM ? O_DIRECT : 0), S_IRUSR | S_IWUSR))); if (fd == -1) { PLOG_TO(SYSTEM, ERROR) << "Faied to open tmp file: " << tmp_file; return; } if (user_id == USER_SYSTEM) { time_point<steady_clock> start, end; uint32_t benchmark_size = 0; uint64_t benchmark_time_ns = 0; ssize_t ret; bool first_write = true; while (size > 0) { start = steady_clock::now(); ret = write(fd, data, MIN(benchmark_unit_size, size)); Loading @@ -252,41 +270,35 @@ void storaged_t::flush_proto_user_system(StoragedProto* proto) { * compute bandwidth after the first write and if write returns * exactly unit size. */ if (size != proto_str.size() && ret == benchmark_unit_size) { if (!first_write && ret == benchmark_unit_size) { benchmark_size += benchmark_unit_size; benchmark_time_ns += duration_cast<nanoseconds>(end - start).count(); } size -= ret; data += ret; first_write = false; } if (benchmark_size) { int perf = benchmark_size * 1000000LLU / benchmark_time_ns; storage_info->update_perf_history(perf, system_clock::now()); } } else { if (!WriteFully(fd, data, size)) { PLOG_TO(SYSTEM, ERROR) << "Faied to write tmp file: " << tmp_file; return; } } fd.reset(-1); /* Atomically replace existing proto file to reduce chance of data loss. */ rename(tmp_file.c_str(), proto_file.c_str()); } void storaged_t::flush_proto(userid_t user_id, StoragedProto* proto) { prepare_proto(user_id, proto); if (user_id == USER_SYSTEM) { flush_proto_user_system(proto); return; } unique_ptr<char> proto_data(prepare_proto(user_id, proto)); if (proto_data == nullptr) return; string proto_file = proto_path(user_id); string tmp_file = proto_file + "_tmp"; if (!WriteStringToFile(proto->SerializeAsString(), tmp_file, S_IRUSR | S_IWUSR)) { return; } /* Atomically replace existing proto file to reduce chance of data loss. */ rename(tmp_file.c_str(), proto_file.c_str()); flush_proto_data(user_id, proto_data.get(), proto->ByteSize()); } void storaged_t::flush_protos(unordered_map<int, StoragedProto>* protos) { Loading storaged/storaged.proto +1 −1 Original line number Diff line number Diff line Loading @@ -56,5 +56,5 @@ message StoragedProto { optional uint32 version = 2; optional UidIOUsage uid_io_usage = 3; optional IOPerfHistory perf_history = 4; repeated uint32 padding = 5; optional bytes padding = 5; } Loading
storaged/include/storaged.h +6 −3 Original line number Diff line number Diff line Loading @@ -36,6 +36,9 @@ friend class test_case_name##_##test_name##_Test #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define IS_ALIGNED(x, align) (!((x) & ((align) - 1))) #define ROUND_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) #define SECTOR_SIZE ( 512 ) #define SEC_TO_MSEC ( 1000 ) #define MSEC_TO_USEC ( 1000 ) Loading Loading @@ -83,12 +86,12 @@ class storaged_t : public android::hardware::health::V2_0::IHealthInfoCallback, time_t mStarttime; sp<android::hardware::health::V2_0::IHealth> health; unique_ptr<storage_info_t> storage_info; static const uint32_t crc_init; static const uint32_t current_version; unordered_map<userid_t, bool> proto_loaded; void load_proto(userid_t user_id); void prepare_proto(userid_t user_id, StoragedProto* proto); char* prepare_proto(userid_t user_id, StoragedProto* proto); void flush_proto(userid_t user_id, StoragedProto* proto); void flush_proto_user_system(StoragedProto* proto); void flush_proto_data(userid_t user_id, const char* data, ssize_t size); string proto_path(userid_t user_id) { return string("/data/misc_ce/") + to_string(user_id) + "/storaged/storaged.proto"; Loading
storaged/storaged.cpp +79 −67 Original line number Diff line number Diff line Loading @@ -54,11 +54,13 @@ namespace { */ constexpr int USER_SYSTEM = 0; constexpr uint32_t benchmark_unit_size = 16 * 1024; // 16KB constexpr ssize_t benchmark_unit_size = 16 * 1024; // 16KB constexpr ssize_t min_benchmark_size = 128 * 1024; // 128KB } // namespace const uint32_t storaged_t::crc_init = 0x5108A4ED; /* STORAGED */ const uint32_t storaged_t::current_version = 4; using android::hardware::health::V1_0::BatteryStatus; using android::hardware::health::V1_0::toString; Loading Loading @@ -186,14 +188,11 @@ void storaged_t::load_proto(userid_t user_id) { StoragedProto proto; proto.ParseFromString(ss.str()); uint32_t crc = proto.crc(); proto.set_crc(crc_init); string proto_str = proto.SerializeAsString(); uint32_t computed_crc = crc32(crc_init, reinterpret_cast<const Bytef*>(proto_str.c_str()), proto_str.size()); if (crc != computed_crc) { const UidIOUsage& uid_io_usage = proto.uid_io_usage(); uint32_t computed_crc = crc32(current_version, reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), uid_io_usage.ByteSize()); if (proto.crc() != computed_crc) { LOG_TO(SYSTEM, WARNING) << "CRC mismatch in " << proto_file; return; } Loading @@ -205,41 +204,60 @@ void storaged_t::load_proto(userid_t user_id) { } } void storaged_t:: prepare_proto(userid_t user_id, StoragedProto* proto) { proto->set_version(3); proto->set_crc(crc_init); char* storaged_t:: prepare_proto(userid_t user_id, StoragedProto* proto) { proto->set_version(current_version); const UidIOUsage& uid_io_usage = proto->uid_io_usage(); proto->set_crc(crc32(current_version, reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()), uid_io_usage.ByteSize())); uint32_t pagesize = sysconf(_SC_PAGESIZE); if (user_id == USER_SYSTEM) { while (proto->ByteSize() < 128 * 1024) { proto->add_padding(0xFEEDBABE); proto->set_padding("", 1); vector<char> padding; ssize_t size = ROUND_UP(MAX(min_benchmark_size, proto->ByteSize()), pagesize); padding = vector<char>(size - proto->ByteSize(), 0xFD); proto->set_padding(padding.data(), padding.size()); while (!IS_ALIGNED(proto->ByteSize(), pagesize)) { padding.push_back(0xFD); proto->set_padding(padding.data(), padding.size()); } } string proto_str = proto->SerializeAsString(); proto->set_crc(crc32(crc_init, reinterpret_cast<const Bytef*>(proto_str.c_str()), proto_str.size())); char* data = nullptr; if (posix_memalign(reinterpret_cast<void**>(&data), pagesize, proto->ByteSize())) { PLOG_TO(SYSTEM, ERROR) << "Faied to alloc aligned buffer (size: " << proto->ByteSize() << ")"; return data; } void storaged_t::flush_proto_user_system(StoragedProto* proto) { string proto_str = proto->SerializeAsString(); const char* data = proto_str.data(); uint32_t size = proto_str.size(); ssize_t ret; time_point<steady_clock> start, end; proto->SerializeToArray(data, proto->ByteSize()); return data; } string proto_file = proto_path(USER_SYSTEM); void storaged_t::flush_proto_data(userid_t user_id, const char* data, ssize_t size) { string proto_file = proto_path(user_id); string tmp_file = proto_file + "_tmp"; unique_fd fd(TEMP_FAILURE_RETRY(open(tmp_file.c_str(), O_DIRECT | O_SYNC | O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, O_SYNC | O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC | (user_id == USER_SYSTEM ? O_DIRECT : 0), S_IRUSR | S_IWUSR))); if (fd == -1) { PLOG_TO(SYSTEM, ERROR) << "Faied to open tmp file: " << tmp_file; return; } if (user_id == USER_SYSTEM) { time_point<steady_clock> start, end; uint32_t benchmark_size = 0; uint64_t benchmark_time_ns = 0; ssize_t ret; bool first_write = true; while (size > 0) { start = steady_clock::now(); ret = write(fd, data, MIN(benchmark_unit_size, size)); Loading @@ -252,41 +270,35 @@ void storaged_t::flush_proto_user_system(StoragedProto* proto) { * compute bandwidth after the first write and if write returns * exactly unit size. */ if (size != proto_str.size() && ret == benchmark_unit_size) { if (!first_write && ret == benchmark_unit_size) { benchmark_size += benchmark_unit_size; benchmark_time_ns += duration_cast<nanoseconds>(end - start).count(); } size -= ret; data += ret; first_write = false; } if (benchmark_size) { int perf = benchmark_size * 1000000LLU / benchmark_time_ns; storage_info->update_perf_history(perf, system_clock::now()); } } else { if (!WriteFully(fd, data, size)) { PLOG_TO(SYSTEM, ERROR) << "Faied to write tmp file: " << tmp_file; return; } } fd.reset(-1); /* Atomically replace existing proto file to reduce chance of data loss. */ rename(tmp_file.c_str(), proto_file.c_str()); } void storaged_t::flush_proto(userid_t user_id, StoragedProto* proto) { prepare_proto(user_id, proto); if (user_id == USER_SYSTEM) { flush_proto_user_system(proto); return; } unique_ptr<char> proto_data(prepare_proto(user_id, proto)); if (proto_data == nullptr) return; string proto_file = proto_path(user_id); string tmp_file = proto_file + "_tmp"; if (!WriteStringToFile(proto->SerializeAsString(), tmp_file, S_IRUSR | S_IWUSR)) { return; } /* Atomically replace existing proto file to reduce chance of data loss. */ rename(tmp_file.c_str(), proto_file.c_str()); flush_proto_data(user_id, proto_data.get(), proto->ByteSize()); } void storaged_t::flush_protos(unordered_map<int, StoragedProto>* protos) { Loading
storaged/storaged.proto +1 −1 Original line number Diff line number Diff line Loading @@ -56,5 +56,5 @@ message StoragedProto { optional uint32 version = 2; optional UidIOUsage uid_io_usage = 3; optional IOPerfHistory perf_history = 4; repeated uint32 padding = 5; optional bytes padding = 5; }