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

Commit 8ec3fa8a authored by Akilesh Kailash's avatar Akilesh Kailash
Browse files

libsnapshot: Retrieve base sector for dm-user device creation



dm-user device requires sector information which is retrieved
from snapuserd daemon once the metadata read is completed.
Split up the initialization of daemon into two APIs. Once
the metadata read is completed, send the sector information
back to libsnapshot to create the dm-user device.

On a sidenote, remove unused code from snapuserd_client

Bug: 168311203
Test: vts_libsnapshot_test, cow_snapuserd_test

Signed-off-by: default avatarAkilesh Kailash <akailash@google.com>
Change-Id: I0647ebbeea3a4705599966974bfec2318a3e1e4e
parent 99ed2152
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