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

Commit 58b77fb1 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 5357520 from 95a5a051 to qt-release

Change-Id: I1ff76fe43e53be8d9e5613c4774556f9e9c3f906
parents 8cdfc17a 95a5a051
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ static void dump_all_maps(log_t* log, unwindstack::Unwinder* unwinder, uint64_t
  std::shared_ptr<unwindstack::Memory>& process_memory = unwinder->GetProcessMemory();

  std::string line;
  for (unwindstack::MapInfo* map_info : *maps) {
  for (auto const& map_info : *maps) {
    line = "    ";
    if (print_fault_address_marker) {
      if (addr < map_info->start) {
+26 −13
Original line number Diff line number Diff line
@@ -263,35 +263,43 @@ int main(int argc, char* argv[]) {

    // Check verity and optionally setup overlayfs backing.
    auto reboot_later = false;
    auto uses_overlayfs = fs_mgr_overlayfs_valid() != OverlayfsValidResult::kNotSupported;
    for (auto it = partitions.begin(); it != partitions.end();) {
        auto& entry = *it;
        auto& mount_point = entry.mount_point;
        if (fs_mgr_is_verity_enabled(entry)) {
            LOG(WARNING) << "Verity enabled on " << mount_point;
            if (can_reboot &&
                (android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked")) {
            retval = VERITY_PARTITION;
            if (android::base::GetProperty("ro.boot.vbmeta.devices_state", "") != "locked") {
                if (AvbOps* ops = avb_ops_user_new()) {
                    auto ret = avb_user_verity_set(
                            ops, android::base::GetProperty("ro.boot.slot_suffix", "").c_str(),
                            false);
                    avb_ops_user_free(ops);
                    if (ret) {
                        if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
                            retval = VERITY_PARTITION;
                        LOG(WARNING) << "Disable verity for " << mount_point;
                        reboot_later = can_reboot;
                        if (reboot_later) {
                            // w/o overlayfs available, also check for dedupe
                            reboot_later = true;
                            if (!uses_overlayfs) {
                                ++it;
                                continue;
                            }
                            reboot(false);
                        }
                    } else if (fs_mgr_set_blk_ro(entry.blk_device, false)) {
                        fec::io fh(entry.blk_device.c_str(), O_RDWR);
                        if (fh && fh.set_verity_status(false)) reboot_later = true;
                        if (fh && fh.set_verity_status(false)) {
                            LOG(WARNING) << "Disable verity for " << mount_point;
                            reboot_later = can_reboot;
                            if (reboot_later && !uses_overlayfs) {
                                ++it;
                                continue;
                            }
                        }
                    }
                }
            }
            LOG(ERROR) << "Skipping " << mount_point;
            retval = VERITY_PARTITION;
            it = partitions.erase(it);
            continue;
        }
@@ -318,7 +326,8 @@ int main(int argc, char* argv[]) {
    }

    // Mount overlayfs.
    if (!fs_mgr_overlayfs_mount_all(&partitions)) {
    errno = 0;
    if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
        retval = BAD_OVERLAY;
        PLOG(ERROR) << "Can not mount overlayfs for partitions";
    }
@@ -346,11 +355,15 @@ int main(int argc, char* argv[]) {
                break;
            }
            if ((mount_point == "/") && (rentry.mount_point == "/system")) {
                if (blk_device != "/dev/root") blk_device = rentry.blk_device;
                blk_device = rentry.blk_device;
                mount_point = "/system";
                break;
            }
        }
        if (blk_device == "/dev/root") {
            auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
            if (from_fstab) blk_device = from_fstab->blk_device;
        }
        fs_mgr_set_blk_ro(blk_device, false);

        // Now remount!
+7 −3
Original line number Diff line number Diff line
@@ -20,13 +20,17 @@ cc_library_static {
    recovery_available: true,
    export_include_dirs: ["include"],
    cflags: [
        // TODO(b/121211685): Allows us to create a skeleton of required classes
        "-Wno-unused-private-field",
        "-Wno-unused-parameter",
        "-D_FILE_OFFSET_BITS=64",
    ],

    srcs: [
        "fiemap_writer.cpp",
        "split_fiemap_writer.cpp",
        "utility.cpp",
    ],

    static_libs: [
        "libext4_utils",
    ],

    header_libs: [
+109 −25
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <sys/vfs.h>
#include <unistd.h>

#include <limits>
#include <string>
#include <utility>
#include <vector>
@@ -206,8 +207,13 @@ static bool PerformFileChecks(const std::string& file_path, uint64_t file_size,
    }

    // Check if the filesystem is of supported types.
    // Only ext4 and f2fs are tested and supported.
    if ((sfs.f_type != EXT4_SUPER_MAGIC) && (sfs.f_type != F2FS_SUPER_MAGIC)) {
    // Only ext4, f2fs, and vfat are tested and supported.
    switch (sfs.f_type) {
        case EXT4_SUPER_MAGIC:
        case F2FS_SUPER_MAGIC:
        case MSDOS_SUPER_MAGIC:
            break;
        default:
            LOG(ERROR) << "Unsupported file system type: 0x" << std::hex << sfs.f_type;
            return false;
    }
@@ -224,13 +230,45 @@ static bool PerformFileChecks(const std::string& file_path, uint64_t file_size,
}

static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blocksz,
                         uint64_t file_size, std::function<bool(uint64_t, uint64_t)> on_progress) {
                         uint64_t file_size, unsigned int fs_type,
                         std::function<bool(uint64_t, uint64_t)> on_progress) {
    // Reserve space for the file on the file system and write it out to make sure the extents
    // don't come back unwritten. Return from this function with the kernel file offset set to 0.
    // If the filesystem is f2fs, then we also PIN the file on disk to make sure the blocks
    // aren't moved around.
    if (fallocate64(file_fd, FALLOC_FL_ZERO_RANGE, 0, file_size)) {
        PLOG(ERROR) << "Failed to allocate space for file: " << file_path << " size: " << file_size;
    switch (fs_type) {
        case EXT4_SUPER_MAGIC:
        case F2FS_SUPER_MAGIC:
            if (fallocate(file_fd, FALLOC_FL_ZERO_RANGE, 0, file_size)) {
                PLOG(ERROR) << "Failed to allocate space for file: " << file_path
                            << " size: " << file_size;
                return false;
            }
            break;
        case MSDOS_SUPER_MAGIC: {
            // fallocate() is not supported, and not needed, since VFAT does not support holes.
            // Instead we can perform a much faster allocation.
            auto offset = TEMP_FAILURE_RETRY(lseek(file_fd, file_size - 1, SEEK_SET));
            if (offset < 0) {
                PLOG(ERROR) << "Failed to lseek " << file_path;
                return false;
            }
            if (offset != file_size - 1) {
                LOG(ERROR) << "Seek returned wrong offset " << offset << " for file " << file_path;
                return false;
            }
            char buffer[] = {0};
            if (!android::base::WriteFully(file_fd, buffer, 1)) {
                PLOG(ERROR) << "Write failed: " << file_path;
                return false;
            }
            if (on_progress && !on_progress(file_size, file_size)) {
                return false;
            }
            return true;
        }
        default:
            LOG(ERROR) << "Missing fallocate() support for file system " << fs_type;
            return false;
    }

@@ -286,9 +324,9 @@ static bool AllocateFile(int file_fd, const std::string& file_path, uint64_t blo
}

static bool PinFile(int file_fd, const std::string& file_path, uint32_t fs_type) {
    if (fs_type == EXT4_SUPER_MAGIC) {
        // No pinning necessary for ext4. The blocks, once allocated, are expected
        // to be fixed.
    if (fs_type != F2FS_SUPER_MAGIC) {
        // No pinning necessary for ext4/msdos. The blocks, once allocated, are
        // expected to be fixed.
        return true;
    }

@@ -323,9 +361,9 @@ static bool PinFile(int file_fd, const std::string& file_path, uint32_t fs_type)
}

static bool IsFilePinned(int file_fd, const std::string& file_path, uint32_t fs_type) {
    if (fs_type == EXT4_SUPER_MAGIC) {
        // No pinning necessary for ext4. The blocks, once allocated, are expected
        // to be fixed.
    if (fs_type != F2FS_SUPER_MAGIC) {
        // No pinning necessary for ext4 or vfat. The blocks, once allocated,
        // are expected to be fixed.
        return true;
    }

@@ -437,6 +475,44 @@ static bool ReadFiemap(int file_fd, const std::string& file_path,
    return last_extent_seen;
}

static bool ReadFibmap(int file_fd, const std::string& file_path,
                       std::vector<struct fiemap_extent>* extents) {
    struct stat s;
    if (fstat(file_fd, &s)) {
        PLOG(ERROR) << "Failed to stat " << file_path;
        return false;
    }

    uint64_t num_blocks = (s.st_size + s.st_blksize - 1) / s.st_blksize;
    if (num_blocks > std::numeric_limits<uint32_t>::max()) {
        LOG(ERROR) << "Too many blocks for FIBMAP (" << num_blocks << ")";
        return false;
    }

    for (uint32_t last_block, block_number = 0; block_number < num_blocks; block_number++) {
        uint32_t block = block_number;
        if (ioctl(file_fd, FIBMAP, &block)) {
            PLOG(ERROR) << "Failed to get FIBMAP for file " << file_path;
            return false;
        }
        if (!block) {
            LOG(ERROR) << "Logical block " << block_number << " is a hole, which is not supported";
            return false;
        }

        if (!extents->empty() && block == last_block + 1) {
            extents->back().fe_length++;
        } else {
            extents->push_back(fiemap_extent{.fe_logical = block_number,
                                             .fe_physical = block,
                                             .fe_length = 1,
                                             .fe_flags = 0});
        }
        last_block = block;
    }
    return true;
}

FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_size, bool create,
                                   std::function<bool(uint64_t, uint64_t)> progress) {
    // if 'create' is false, open an existing file and do not truncate.
@@ -505,7 +581,7 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s
    }

    if (create) {
        if (!AllocateFile(file_fd, abs_path, blocksz, file_size, std::move(progress))) {
        if (!AllocateFile(file_fd, abs_path, blocksz, file_size, fs_type, std::move(progress))) {
            LOG(ERROR) << "Failed to allocate file: " << abs_path << " of size: " << file_size
                       << " bytes";
            cleanup(abs_path, create);
@@ -522,11 +598,23 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s

    // now allocate the FiemapWriter and start setting it up
    FiemapUniquePtr fmap(new FiemapWriter());
    switch (fs_type) {
        case EXT4_SUPER_MAGIC:
        case F2FS_SUPER_MAGIC:
            if (!ReadFiemap(file_fd, abs_path, &fmap->extents_)) {
                LOG(ERROR) << "Failed to read fiemap of file: " << abs_path;
                cleanup(abs_path, create);
                return nullptr;
            }
            break;
        case MSDOS_SUPER_MAGIC:
            if (!ReadFibmap(file_fd, abs_path, &fmap->extents_)) {
                LOG(ERROR) << "Failed to read fibmap of file: " << abs_path;
                cleanup(abs_path, create);
                return nullptr;
            }
            break;
    }

    fmap->file_path_ = abs_path;
    fmap->bdev_path_ = bdev_path;
@@ -536,14 +624,10 @@ FiemapUniquePtr FiemapWriter::Open(const std::string& file_path, uint64_t file_s
    fmap->fs_type_ = fs_type;
    fmap->block_size_ = blocksz;

    LOG(INFO) << "Successfully created FiemapWriter for file " << abs_path << " on block device "
    LOG(VERBOSE) << "Successfully created FiemapWriter for file " << abs_path << " on block device "
                 << bdev_path;
    return fmap;
}

bool FiemapWriter::Read(off64_t off, uint8_t* buffer, uint64_t size) {
    return false;
}

}  // namespace fiemap_writer
}  // namespace android
+87 −9
Original line number Diff line number Diff line
@@ -33,8 +33,10 @@
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <libdm/loop_control.h>

#include <libfiemap_writer/fiemap_writer.h>
#include <libfiemap_writer/split_fiemap_writer.h>

#include "utility.h"

using namespace std;
using namespace std::string_literals;
@@ -59,6 +61,24 @@ class FiemapWriterTest : public ::testing::Test {
    std::string testfile;
};

class SplitFiemapTest : public ::testing::Test {
  protected:
    void SetUp() override {
        const ::testing::TestInfo* tinfo = ::testing::UnitTest::GetInstance()->current_test_info();
        testfile = gTestDir + "/"s + tinfo->name();
    }

    void TearDown() override {
        std::string message;
        if (!SplitFiemap::RemoveSplitFiles(testfile, &message)) {
            cerr << "Could not remove all split files: " << message;
        }
    }

    // name of the file we use for testing
    std::string testfile;
};

TEST_F(FiemapWriterTest, CreateImpossiblyLargeFile) {
    // Try creating a file of size ~100TB but aligned to
    // 512 byte to make sure block alignment tests don't
@@ -71,8 +91,7 @@ TEST_F(FiemapWriterTest, CreateImpossiblyLargeFile) {

TEST_F(FiemapWriterTest, CreateUnalignedFile) {
    // Try creating a file of size 4097 bytes which is guaranteed
    // to be unaligned to all known block sizes. The creation must
    // fail.
    // to be unaligned to all known block sizes.
    FiemapUniquePtr fptr = FiemapWriter::Open(testfile, gBlockSize + 1);
    ASSERT_NE(fptr, nullptr);
    ASSERT_EQ(fptr->size(), gBlockSize * 2);
@@ -87,10 +106,7 @@ TEST_F(FiemapWriterTest, CheckFilePath) {
}

TEST_F(FiemapWriterTest, CheckProgress) {
    std::vector<uint64_t> expected{
            0,
            gBlockSize,
    };
    std::vector<uint64_t> expected;
    size_t invocations = 0;
    auto callback = [&](uint64_t done, uint64_t total) -> bool {
        EXPECT_LT(invocations, expected.size());
@@ -100,9 +116,22 @@ TEST_F(FiemapWriterTest, CheckProgress) {
        return true;
    };

    uint32_t fs_type;
    {
        auto ptr = FiemapWriter::Open(testfile, gBlockSize, true);
        ASSERT_NE(ptr, nullptr);
        fs_type = ptr->fs_type();
    }
    ASSERT_EQ(unlink(testfile.c_str()), 0);

    if (fs_type != MSDOS_SUPER_MAGIC) {
        expected.push_back(0);
    }
    expected.push_back(gBlockSize);

    auto ptr = FiemapWriter::Open(testfile, gBlockSize, true, std::move(callback));
    EXPECT_NE(ptr, nullptr);
    EXPECT_EQ(invocations, 2);
    EXPECT_EQ(invocations, expected.size());
}

TEST_F(FiemapWriterTest, CheckPinning) {
@@ -159,6 +188,52 @@ TEST_F(FiemapWriterTest, FileDeletedOnError) {
    EXPECT_EQ(errno, ENOENT);
}

TEST_F(FiemapWriterTest, MaxBlockSize) {
    ASSERT_GT(DetermineMaximumFileSize(testfile), 0);
}

TEST_F(SplitFiemapTest, Create) {
    auto ptr = SplitFiemap::Create(testfile, 1024 * 768, 1024 * 32);
    ASSERT_NE(ptr, nullptr);

    auto extents = ptr->extents();

    // Destroy the fiemap, closing file handles. This should not delete them.
    ptr = nullptr;

    std::vector<std::string> files;
    ASSERT_TRUE(SplitFiemap::GetSplitFileList(testfile, &files));
    for (const auto& path : files) {
        EXPECT_EQ(access(path.c_str(), F_OK), 0);
    }

    ASSERT_GE(extents.size(), files.size());
}

TEST_F(SplitFiemapTest, Open) {
    {
        auto ptr = SplitFiemap::Create(testfile, 1024 * 768, 1024 * 32);
        ASSERT_NE(ptr, nullptr);
    }

    auto ptr = SplitFiemap::Open(testfile);
    ASSERT_NE(ptr, nullptr);

    auto extents = ptr->extents();
    ASSERT_GE(extents.size(), 24);
}

TEST_F(SplitFiemapTest, DeleteOnFail) {
    auto ptr = SplitFiemap::Create(testfile, 1024 * 1024 * 10, 1);
    ASSERT_EQ(ptr, nullptr);

    std::string first_file = testfile + ".0001";
    ASSERT_NE(access(first_file.c_str(), F_OK), 0);
    ASSERT_EQ(errno, ENOENT);
    ASSERT_NE(access(testfile.c_str(), F_OK), 0);
    ASSERT_EQ(errno, ENOENT);
}

class VerifyBlockWritesExt4 : public ::testing::Test {
    // 2GB Filesystem and 4k block size by default
    static constexpr uint64_t block_size = 4096;
@@ -273,7 +348,10 @@ int main(int argc, char** argv) {
        cerr << "unable to create tempdir on " << argv[1] << "\n";
        exit(EXIT_FAILURE);
    }
    gTestDir = tempdir;
    if (!android::base::Realpath(tempdir, &gTestDir)) {
        cerr << "unable to find realpath for " << tempdir;
        exit(EXIT_FAILURE);
    }

    if (argc > 2) {
        testfile_size = strtoull(argv[2], NULL, 0);
Loading