summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJin Qian <jinqian@google.com>2017-12-12 18:38:25 -0800
committerJin Qian <jinqian@google.com>2017-12-13 15:54:55 -0800
commit4c23c4576b809757ef1c48f59032a4aada276602 (patch)
tree6a36e0f5ea049c3412df65f80ce3662ffd85ffbc
parent9c6587ad1fde2f0b820634b5af5007897ef328c0 (diff)
downloadsystem_core-4c23c4576b809757ef1c48f59032a4aada276602.tar.gz
system_core-4c23c4576b809757ef1c48f59032a4aada276602.tar.bz2
system_core-4c23c4576b809757ef1c48f59032a4aada276602.zip
storaged: align buffer address and size for direct_io
O_DIRECT requires buffer address and size to be aligned Bug: 63629306 Change-Id: I268abb1c0ba32af4fd2e92210192c47a1f173238
-rw-r--r--storaged/include/storaged.h9
-rw-r--r--storaged/storaged.cpp146
-rw-r--r--storaged/storaged.proto2
3 files changed, 86 insertions, 71 deletions
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index e5dd70d2c..6bf6c9c1a 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -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 )
@@ -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";
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 915c09534..ff0de29b9 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -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;
@@ -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;
}
@@ -205,88 +204,101 @@ 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,
- S_IRUSR | S_IWUSR)));
+ 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;
}
- uint32_t benchmark_size = 0;
- uint64_t benchmark_time_ns = 0;
- while (size > 0) {
- start = steady_clock::now();
- ret = write(fd, data, MIN(benchmark_unit_size, size));
- if (ret <= 0) {
+ 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));
+ if (ret <= 0) {
+ PLOG_TO(SYSTEM, ERROR) << "Faied to write tmp file: " << tmp_file;
+ return;
+ }
+ end = steady_clock::now();
+ /*
+ * compute bandwidth after the first write and if write returns
+ * exactly 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;
}
- end = steady_clock::now();
- /*
- * compute bandwidth after the first write and if write returns
- * exactly unit size.
- */
- if (size != proto_str.size() && ret == benchmark_unit_size) {
- benchmark_size += benchmark_unit_size;
- benchmark_time_ns += duration_cast<nanoseconds>(end - start).count();
- }
- size -= ret;
- data += ret;
- }
-
- if (benchmark_size) {
- int perf = benchmark_size * 1000000LLU / benchmark_time_ns;
- storage_info->update_perf_history(perf, system_clock::now());
}
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) {
diff --git a/storaged/storaged.proto b/storaged/storaged.proto
index 9dcd79ec0..2000c0b92 100644
--- a/storaged/storaged.proto
+++ b/storaged/storaged.proto
@@ -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;
}