Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c949326 authored by Kelvin Zhang's avatar Kelvin Zhang Committed by Gerrit Code Review
Browse files

Merge "Make partition metadata write atomic" into main

parents 5233181d 78d53522
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -111,13 +111,7 @@ bool SaveMetadata(MetadataBuilder* builder, const std::string& metadata_dir) {
        return true;
    }

    unique_fd fd(open(metadata_file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY | O_SYNC, 0644));
    if (fd < 0) {
        LOG(ERROR) << "open failed: " << metadata_file;
        return false;
    }

    if (!WriteToImageFile(fd, *exported.get())) {
    if (!WriteToImageFile(metadata_file, *exported.get())) {
        LOG(ERROR) << "Unable to save new metadata";
        return false;
    }
+39 −5
Original line number Diff line number Diff line
@@ -123,13 +123,46 @@ bool WriteToImageFile(borrowed_fd fd, const LpMetadata& input) {
    return true;
}

#if !defined(_WIN32)
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;
}
#endif

bool WriteToImageFile(const std::string& file, const LpMetadata& input) {
    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY, 0644));
    if (fd < 0) {
        PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
    const auto parent_dir = base::Dirname(file);
    TemporaryFile tmpfile(parent_dir);
    if (!WriteToImageFile(tmpfile.fd, input)) {
        PLOG(ERROR) << "Failed to write geometry data to tmpfile " << tmpfile.path;
        return false;
    }
    return WriteToImageFile(fd, input);

#if !defined(_WIN32)
    fsync(tmpfile.fd);
#endif
    const auto err = rename(tmpfile.path, file.c_str());
    if (err != 0) {
        PLOG(ERROR) << "Failed to rename tmp geometry file " << tmpfile.path << " to " << file;
        return false;
    }
#if !defined(_WIN32)
    FsyncDirectory(parent_dir.c_str());
#endif
    return true;
}

ImageBuilder::ImageBuilder(const LpMetadata& metadata, uint32_t block_size,
@@ -208,7 +241,8 @@ bool ImageBuilder::ExportFiles(const std::string& output_dir) {
        std::string file_name = "super_" + name + ".img";
        std::string file_path = output_dir + "/" + file_name;

        static const int kOpenFlags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
        static const int kOpenFlags =
                O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
        unique_fd fd(open(file_path.c_str(), kOpenFlags, 0644));
        if (fd < 0) {
            PERROR << "open failed: " << file_path;