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

Commit 70d27113 authored by Akilesh Kailash's avatar Akilesh Kailash Committed by Gerrit Code Review
Browse files

Merge "libsnapshot: Retrieve base sector for dm-user device creation"

parents 3d0f195b 8ec3fa8a
Loading
Loading
Loading
Loading
+20 −17
Original line number Diff line number Diff line
@@ -108,6 +108,8 @@ class SnapuserdTest : public ::testing::Test {
    std::unique_ptr<uint8_t[]> product_buffer_;

    void Init();
    void InitCowDevices();
    void InitDaemon();
    void CreateCowDevice(std::unique_ptr<TemporaryFile>& cow);
    void CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow);
    void CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow);
@@ -238,12 +240,6 @@ void SnapuserdTest::CreateSystemDmUser(std::unique_ptr<TemporaryFile>& cow) {
    system_device_name_.clear();
    system_device_ctrl_name_.clear();

    // Create a COW device. Number of sectors is chosen random which can
    // hold at least 400MB of data

    int err = ioctl(sys_fd_.get(), BLKGETSIZE, &system_blksize_);
    ASSERT_GE(err, 0);

    std::string str(cow->path);
    std::size_t found = str.find_last_of("/\\");
    ASSERT_NE(found, std::string::npos);
@@ -280,12 +276,6 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) {
    product_device_name_.clear();
    product_device_ctrl_name_.clear();

    // Create a COW device. Number of sectors is chosen random which can
    // hold at least 400MB of data

    int err = ioctl(product_fd_.get(), BLKGETSIZE, &product_blksize_);
    ASSERT_GE(err, 0);

    std::string str(cow->path);
    std::size_t found = str.find_last_of("/\\");
    ASSERT_NE(found, std::string::npos);
@@ -297,12 +287,15 @@ void SnapuserdTest::CreateProductDmUser(std::unique_ptr<TemporaryFile>& cow) {
    system(cmd.c_str());
}

void SnapuserdTest::StartSnapuserdDaemon() {
    ASSERT_TRUE(EnsureSnapuserdStarted());
void SnapuserdTest::InitCowDevices() {
    system_blksize_ = client_->InitDmUserCow(cow_system_->path);
    ASSERT_NE(system_blksize_, 0);

    client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s);
    ASSERT_NE(client_, nullptr);
    product_blksize_ = client_->InitDmUserCow(cow_product_->path);
    ASSERT_NE(product_blksize_, 0);
}

void SnapuserdTest::InitDaemon() {
    bool ok = client_->InitializeSnapuserd(cow_system_->path, system_a_loop_->device(),
                                           GetSystemControlPath());
    ASSERT_TRUE(ok);
@@ -312,6 +305,13 @@ void SnapuserdTest::StartSnapuserdDaemon() {
    ASSERT_TRUE(ok);
}

void SnapuserdTest::StartSnapuserdDaemon() {
    ASSERT_TRUE(EnsureSnapuserdStarted());

    client_ = SnapuserdClient::Connect(kSnapuserdSocket, 5s);
    ASSERT_NE(client_, nullptr);
}

void SnapuserdTest::CreateSnapshotDevices() {
    std::string cmd;

@@ -435,10 +435,13 @@ TEST_F(SnapuserdTest, ReadWrite) {
    CreateCowDevice(cow_system_);
    CreateCowDevice(cow_product_);

    StartSnapuserdDaemon();
    InitCowDevices();

    CreateSystemDmUser(cow_system_);
    CreateProductDmUser(cow_product_);

    StartSnapuserdDaemon();
    InitDaemon();

    CreateSnapshotDevices();

+9 −10
Original line number Diff line number Diff line
@@ -61,23 +61,19 @@ class BufferSink : public IByteSink {

class Snapuserd final {
  public:
    Snapuserd(const std::string& in_cow_device, const std::string& in_backing_store_device,
              const std::string& in_control_device)
        : cow_device_(in_cow_device),
          backing_store_device_(in_backing_store_device),
          control_device_(in_control_device),
          metadata_read_done_(false) {}

    bool Init();
    bool InitBackingAndControlDevice(std::string& backing_device, std::string& control_device);
    bool InitCowDevice(std::string& cow_device);
    int Run();
    const std::string& GetControlDevicePath() { return control_device_; }
    const std::string& GetCowDevice() { return cow_device_; }
    uint64_t GetNumSectors() { return num_sectors_; }

  private:
    int ReadDmUserHeader();
    bool ReadDmUserPayload(void* buffer, size_t size);
    int WriteDmUserPayload(size_t size);
    int ConstructKernelCowHeader();
    int ReadMetadata();
    bool ReadMetadata();
    int ZerofillDiskExceptions(size_t read_size);
    int ReadDiskExceptions(chunk_t chunk, size_t size);
    int ReadData(chunk_t chunk, size_t size);
@@ -94,6 +90,8 @@ class Snapuserd final {
                             int unmerged_exceptions);
    bool AdvanceMergedOps(int merged_ops_cur_iter);
    bool ProcessMergeComplete(chunk_t chunk, void* buffer);
    sector_t ChunkToSector(chunk_t chunk) { return chunk << CHUNK_SHIFT; }
    chunk_t SectorToChunk(sector_t sector) { return sector >> CHUNK_SHIFT; }

    std::string cow_device_;
    std::string backing_store_device_;
@@ -104,6 +102,7 @@ class Snapuserd final {
    unique_fd ctrl_fd_;

    uint32_t exceptions_per_area_;
    uint64_t num_sectors_;

    std::unique_ptr<ICowOpIter> cowop_iter_;
    std::unique_ptr<ICowOpReverseIter> cowop_riter_;
@@ -118,7 +117,7 @@ class Snapuserd final {
    // Value - cow operation
    std::unordered_map<chunk_t, const CowOperation*> chunk_map_;

    bool metadata_read_done_;
    bool metadata_read_done_ = false;
    BufferSink bufsink_;
};

+1 −1
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ class SnapuserdClient {
                                                    std::chrono::milliseconds timeout_ms);

    bool StopSnapuserd();
    int RestartSnapuserd(std::vector<std::vector<std::string>>& vec);
    uint64_t InitDmUserCow(const std::string& cow_device);
    bool InitializeSnapuserd(const std::string& cow_device, const std::string& backing_device,
                             const std::string& control_device);

+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ namespace snapshot {
static constexpr uint32_t MAX_PACKET_SIZE = 512;

enum class DaemonOperations {
    INIT,
    START,
    QUERY,
    STOP,
+19 −22
Original line number Diff line number Diff line
@@ -386,24 +386,6 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name,

    auto& dm = DeviceMapper::Instance();

    // Use the size of the base device for the COW device. It doesn't really
    // matter, it just needs to look similar enough so the kernel doesn't complain
    // about alignment or being too small.
    uint64_t base_sectors = 0;
    {
        unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC));
        if (fd < 0) {
            PLOG(ERROR) << "open failed: " << base_device;
            return false;
        }
        auto dev_size = get_block_device_size(fd);
        if (!dev_size) {
            PLOG(ERROR) << "Could not determine block device size: " << base_device;
            return false;
        }
        base_sectors = dev_size / kSectorSize;
    }

    // Use an extra decoration for first-stage init, so we can transition
    // to a new table entry in second-stage.
    std::string misc_name = name;
@@ -411,13 +393,19 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name,
        misc_name += "-init";
    }

    DmTable table;
    table.Emplace<DmTargetUser>(0, base_sectors, misc_name);
    if (!dm.CreateDevice(name, table, path, timeout_ms)) {
    if (!EnsureSnapuserdConnected()) {
        return false;
    }

    if (!EnsureSnapuserdConnected()) {
    uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_file);
    if (base_sectors == 0) {
        LOG(ERROR) << "Failed to retrieve base_sectors from Snapuserd";
        return false;
    }

    DmTable table;
    table.Emplace<DmTargetUser>(0, base_sectors, misc_name);
    if (!dm.CreateDevice(name, table, path, timeout_ms)) {
        return false;
    }

@@ -1366,6 +1354,15 @@ bool SnapshotManager::PerformSecondStageTransition() {
            continue;
        }

        uint64_t base_sectors = snapuserd_client_->InitDmUserCow(cow_device);
        if (base_sectors == 0) {
            // Unrecoverable as metadata reads from cow device failed
            LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd";
            return false;
        }

        CHECK(base_sectors == target.spec.length);

        if (!snapuserd_client_->InitializeSnapuserd(cow_device, backing_device, control_device)) {
            // This error is unrecoverable. We cannot proceed because reads to
            // the underlying device will fail.
Loading