Fsync data after writing prefs
update_engine is relying on prefs stored on filesystem to resume OTA
progress. Partners report loss of update progress after forced reboot.
This might be I/O cache issue.
Test: th
Bug: 259174530
Change-Id: I7b4b8281cfe2cc45c51e4d6d60e09edb12f3ed86
diff --git a/common/utils.cc b/common/utils.cc
index e3ffa1c..6b8bc54 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -35,6 +35,7 @@
#include <unistd.h>
#include <algorithm>
+#include <filesystem>
#include <utility>
#include <vector>
@@ -409,6 +410,53 @@
return true;
}
+bool FsyncDirectory(const char* dirname) {
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(dirname, O_RDONLY | O_CLOEXEC)));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << dirname;
+ return false;
+ }
+ if (fsync(fd) == -1) {
+ if (errno == EROFS || errno == EINVAL) {
+ PLOG(WARNING) << "Skip fsync " << dirname
+ << " on a file system does not support synchronization";
+ } else {
+ PLOG(ERROR) << "Failed to fsync " << dirname;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool WriteStringToFileAtomic(const std::string& path,
+ std::string_view content) {
+ const std::string tmp_path = path + ".tmp";
+ {
+ const int flags = O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC;
+ android::base::unique_fd fd(
+ TEMP_FAILURE_RETRY(open(tmp_path.c_str(), flags, 0644)));
+ if (fd == -1) {
+ PLOG(ERROR) << "Failed to open " << path;
+ return false;
+ }
+ if (!WriteAll(fd.get(), content.data(), content.size())) {
+ PLOG(ERROR) << "Failed to write to fd " << fd;
+ return false;
+ }
+ // rename() without fsync() is not safe. Data could still be living on page
+ // cache. To ensure atomiticity, call fsync()
+ if (fsync(fd) != 0) {
+ PLOG(ERROR) << "Failed to fsync " << tmp_path;
+ }
+ }
+ if (rename(tmp_path.c_str(), path.c_str()) == -1) {
+ PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
+ return false;
+ }
+ return FsyncDirectory(std::filesystem::path(path).parent_path().c_str());
+}
+
void HexDumpArray(const uint8_t* const arr, const size_t length) {
LOG(INFO) << "Logging array of length: " << length;
const unsigned int bytes_per_line = 16;