blob: e825af5b6db637d7072baed0ece7f5ece0b1ab97 [file] [log] [blame] [edit]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "dlcservice/lvm/lvmd_proxy_wrapper.h"
#include <memory>
#include <utility>
#include <vector>
#include "dlcservice/system_state.h"
// TODO(b/254557435): Reduce the # of calls made into lvmd.
namespace dlcservice {
namespace {
// CrOS currently only uses "thinpool" as thinpool name.
constexpr char kThinpoolName[] = "thinpool";
} // namespace
LvmdProxyWrapper::LvmdProxyWrapper(
std::unique_ptr<org::chromium::LvmdProxyInterface> lvmd_proxy)
: lvmd_proxy_(std::move(lvmd_proxy)) {}
bool LvmdProxyWrapper::GetPhysicalVolume(const std::string& device_path,
lvmd::PhysicalVolume* pv) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->GetPhysicalVolume(device_path, pv, &err)) {
LOG(WARNING) << "Failed to GetPhysicalVolume from lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::GetVolumeGroup(const lvmd::PhysicalVolume& pv,
lvmd::VolumeGroup* vg) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->GetVolumeGroup(pv, vg, &err)) {
LOG(WARNING) << "Failed to GetVolumeGroup from lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::GetThinpool(const lvmd::VolumeGroup& vg,
lvmd::Thinpool* thinpool) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->GetThinpool(vg, kThinpoolName, thinpool, &err)) {
LOG(WARNING) << "Failed to GetThinpool from lvmd: " << Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::GetLogicalVolume(const lvmd::VolumeGroup& vg,
const std::string& lv_name,
lvmd::LogicalVolume* lv) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->GetLogicalVolume(vg, lv_name, lv, &err)) {
LOG(WARNING) << "Failed to GetLogicalVolume from lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::GetLogicalVolume(const std::string& lv_name,
lvmd::LogicalVolume* lv) {
auto stateful_path =
SystemState::Get()->boot_slot()->GetStatefulPartitionPath();
if (stateful_path.empty()) {
LOG(ERROR) << "Failed to GetStatefulPartitionPath.";
return false;
}
lvmd::PhysicalVolume pv;
if (!GetPhysicalVolume(stateful_path.value(), &pv)) {
LOG(ERROR) << "Failed to GetPhysicalVolume.";
return false;
}
lvmd::VolumeGroup vg;
if (!GetVolumeGroup(pv, &vg)) {
LOG(ERROR) << "Failed to GetVolumeGroup.";
return false;
}
brillo::ErrorPtr err;
if (!lvmd_proxy_->GetLogicalVolume(vg, lv_name, lv, &err)) {
LOG(ERROR) << "Failed to GetLogicalVolume.";
return false;
}
return true;
}
bool LvmdProxyWrapper::CreateLogicalVolume(
const lvmd::Thinpool& thinpool,
const lvmd::LogicalVolumeConfiguration& lv_config,
lvmd::LogicalVolume* lv) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->CreateLogicalVolume(thinpool, lv_config, lv, &err)) {
LOG(WARNING) << "Failed to CreateLogicalVolume in lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::RemoveLogicalVolume(const lvmd::LogicalVolume& lv) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->RemoveLogicalVolume(lv, &err)) {
LOG(WARNING) << "Failed to CreateLogicalVolume in lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::ToggleLogicalVolumeActivation(
const lvmd::LogicalVolume& lv, bool activate) {
brillo::ErrorPtr err;
if (!lvmd_proxy_->ToggleLogicalVolumeActivation(lv, activate, &err)) {
LOG(WARNING) << "Failed to ToggleLogicalVolumeActivation in lvmd: "
<< Error::ToString(err);
return false;
}
return true;
}
bool LvmdProxyWrapper::CreateLogicalVolumes(
const std::vector<lvmd::LogicalVolumeConfiguration>& lv_configs) {
auto stateful_path =
SystemState::Get()->boot_slot()->GetStatefulPartitionPath();
if (stateful_path.empty()) {
LOG(ERROR) << "Failed to GetStatefulPartitionPath.";
return false;
}
lvmd::PhysicalVolume pv;
if (!GetPhysicalVolume(stateful_path.value(), &pv)) {
LOG(ERROR) << "Failed to GetPhysicalVolume.";
return false;
}
lvmd::VolumeGroup vg;
if (!GetVolumeGroup(pv, &vg)) {
LOG(ERROR) << "Failed to GetVolumeGroup.";
return false;
}
lvmd::Thinpool thinpool;
if (!GetThinpool(vg, &thinpool)) {
LOG(ERROR) << "Failed to GetThinpool.";
return false;
}
// Prefer using thinpool's volume group as thinpool is passed into creating
// the logical volumes.
lvmd::LogicalVolume lv;
for (const auto& lv_config : lv_configs) {
auto lv_name = lv_config.name();
if (GetLogicalVolume(thinpool.volume_group(), lv_name, &lv)) {
if (!ToggleLogicalVolumeActivation(lv, /*activate=*/true)) {
LOG(ERROR) << "Failed to ToggleLogicalVolumeActivation name="
<< lv_name;
return false;
}
} else if (SystemState::Get()->resuming_from_hibernate()) {
LOG(ERROR) << "Failed to CreateLogicalVolume "
"during resume from hibernate, name="
<< lv_name;
return false;
} else if (!CreateLogicalVolume(thinpool, lv_config, &lv)) {
LOG(ERROR) << "Failed to CreateLogicalVolume name=" << lv_name;
return false;
}
}
// TODO(b/254373821): Unsparse the logical volumes.
return true;
}
bool LvmdProxyWrapper::RemoveLogicalVolumes(
const std::vector<std::string>& lv_names) {
auto stateful_path =
SystemState::Get()->boot_slot()->GetStatefulPartitionPath();
lvmd::PhysicalVolume pv;
if (!GetPhysicalVolume(stateful_path.value(), &pv)) {
LOG(ERROR) << "Failed to GetPhysicalVolume.";
return false;
}
lvmd::VolumeGroup vg;
if (!GetVolumeGroup(pv, &vg)) {
LOG(ERROR) << "Failed to GetVolumeGroup.";
return false;
}
bool ret = true;
lvmd::LogicalVolume lv;
for (const auto& lv_name : lv_names) {
if (!GetLogicalVolume(vg, lv_name, &lv)) {
LOG(WARNING) << "Failed to GetLogicalVolume name=" << lv_name;
continue;
}
if (!RemoveLogicalVolume(lv)) {
LOG(ERROR) << "Failed to RemoveLogicalVolume name=" << lv_name;
ret = false;
}
}
return ret;
}
bool LvmdProxyWrapper::ActivateLogicalVolume(const std::string& lv_name) {
auto stateful_path =
SystemState::Get()->boot_slot()->GetStatefulPartitionPath();
lvmd::PhysicalVolume pv;
if (!GetPhysicalVolume(stateful_path.value(), &pv)) {
LOG(ERROR) << "Failed to GetPhysicalVolume.";
return false;
}
lvmd::VolumeGroup vg;
if (!GetVolumeGroup(pv, &vg)) {
LOG(ERROR) << "Failed to GetVolumeGroup.";
return false;
}
lvmd::LogicalVolume lv;
if (!GetLogicalVolume(vg, lv_name, &lv)) {
LOG(ERROR) << "Failed to GetLogicalVolume.";
return false;
}
if (!ToggleLogicalVolumeActivation(lv, /*activate=*/true)) {
LOG(ERROR) << "Failed to ToggleLogicalVolumeActivation from lvmd.";
return false;
}
return true;
}
std::string LvmdProxyWrapper::GetLogicalVolumePath(const std::string& lv_name) {
lvmd::LogicalVolume lv;
return GetLogicalVolume(lv_name, &lv) ? lv.path() : "";
}
} // namespace dlcservice