Fsync on directory after rename() call
rename() isn't necessarily atomic, call fsync() on the directory to ensure that changes in fs structure hit the disk. Test: th Bug: 254211456 Change-Id: I2de842f03766a1108e0f54581738fb964989658a
This commit is contained in:
parent
b190f3cbe1
commit
149fa74db5
|
@ -17,6 +17,7 @@
|
|||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -152,6 +153,24 @@ AutoUnmountDevice::~AutoUnmountDevice() {
|
|||
}
|
||||
}
|
||||
|
||||
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& content, const std::string& path) {
|
||||
const std::string tmp_path = path + ".tmp";
|
||||
{
|
||||
|
@ -175,11 +194,11 @@ bool WriteStringToFileAtomic(const std::string& content, const std::string& path
|
|||
PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return FsyncDirectory(std::filesystem::path(path).parent_path().c_str());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Now&) {
|
||||
struct tm now;
|
||||
struct tm now {};
|
||||
time_t t = time(nullptr);
|
||||
localtime_r(&t, &now);
|
||||
return os << std::put_time(&now, "%Y%m%d-%H%M%S");
|
||||
|
|
|
@ -117,6 +117,7 @@ Return InitializeKernelCow(const std::string& device);
|
|||
// Note that rename() is an atomic operation. This function may not work properly if there
|
||||
// is an open fd to |path|, because that fd has an old view of the file.
|
||||
bool WriteStringToFileAtomic(const std::string& content, const std::string& path);
|
||||
bool FsyncDirectory(const char* dirname);
|
||||
|
||||
// Writes current time to a given stream.
|
||||
struct Now {};
|
||||
|
|
Loading…
Reference in New Issue