| #include "NVMeVolume.hpp" |
| |
| #include "NVMeCacheImpl.hpp" |
| |
| using SchedulerClockType = std::chrono::steady_clock; |
| |
| NVMeVolume::NVMeVolume(sdbusplus::asio::object_server& objServer, |
| const std::shared_ptr<sdbusplus::asio::connection>& conn, |
| const std::shared_ptr<NVMeSubsystem>& subsys, |
| const NVMeNSIdentify& ns) : |
| VolumeBase(dynamic_cast<sdbusplus::bus_t&>(*conn), |
| subsys->volumePath(ns.namespaceId).c_str()), |
| NvmeVolumeBase(dynamic_cast<sdbusplus::bus_t&>(*conn), |
| subsys->volumePath(ns.namespaceId).c_str()), |
| path(subsys->volumePath(ns.namespaceId)), objServer(objServer), conn(conn), |
| subsys(subsys) |
| { |
| namespaceId(ns.namespaceId, false); |
| size(ns.size, false); |
| blockSize(ns.blockSize, false); |
| lbaFormat(ns.lbaFormat, false); |
| metadataAtEnd(ns.metadataAtEnd, false); |
| |
| // see init() for other initialisation |
| } |
| |
| void NVMeVolume::init() |
| { |
| deleteInterface = |
| objServer.add_interface(path, "xyz.openbmc_project.Object.Delete"); |
| deleteInterface->register_method( |
| "Delete", [weak{weak_from_this()}](boost::asio::yield_context yield) { |
| auto self = weak.lock(); |
| if (!self) |
| { |
| throw std::runtime_error("volume delete called twice?"); |
| } |
| auto subsys = self->subsys.lock(); |
| if (!subsys) |
| { |
| throw std::runtime_error("nvmesensor is shutting down"); |
| } |
| subsys->deleteVolume(std::move(yield), self); |
| }); |
| deleteInterface->initialize(); |
| |
| VolumeBase::emit_added(); |
| NvmeVolumeBase::emit_added(); |
| |
| /* create the MetricStore interface */ |
| auto scheduler = Scheduler<SchedulerClockType>::getScheduler(path); |
| |
| // NOLINTBEGIN(performance-unnecessary-value-param) |
| auto completeCB = |
| [wealSelf{weak_from_this()}, |
| path{path}](std::string_view name, |
| std::shared_ptr<MetricBase<SchedulerClockType>> metric) { |
| auto self = wealSelf.lock(); |
| if (!self || !self->metricStore) |
| { |
| // TODO: log_level = INFO |
| std::cerr << std::format( |
| "[{}]Metrics interface for controller expired, update signal skipped.\n", |
| path); |
| } |
| if (!metric->isCacheValid()) |
| { |
| // broadcast invalid metric signal |
| self->metricStore->metricUpdated(std::string{name}, {}); |
| return; |
| } |
| |
| auto data = metric->getCache(); |
| std::vector<uint8_t> headerBuf; |
| headerBuf.resize(sizeof(MetricHeader)); |
| MetricHeader& header = |
| // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) |
| *reinterpret_cast<MetricHeader*>(headerBuf.data()); |
| header.lens = boost::endian::little_uint32_t(sizeof(header)); |
| header.version = 0; |
| header.dataFormat = 0; |
| header.startTime = boost::endian::little_uint64_t( |
| std::get<0>(data).time_since_epoch().count()); |
| header.finishTime = boost::endian::little_uint64_t( |
| std::get<1>(data).time_since_epoch().count()); |
| self->metricStore->metricUpdated(std::string{name}, headerBuf); |
| }; |
| // NOLINTEND(performance-unnecessary-value-param) |
| |
| using IdentifyMetric = |
| IdentifyMetric<NVME_IDENTIFY_CNS_NS, SchedulerClockType>; |
| |
| // NOLINTBEGIN(modernize-make-shared) |
| auto identify = std::shared_ptr<IdentifyMetric>(new IdentifyMetric( |
| this->shared_from_this(), scheduler, |
| // Identify info is persist throughout the namespace lifecycle |
| // i.e. from start() to stop() |
| IdentifyMetric::ClockType::duration::max(), |
| std::bind_front(completeCB, IdentifyMetric::identifyIdentifier()))); |
| // NOLINTEND(modernize-make-shared) |
| |
| metricStore.emplace(conn->get_io_context(), conn, path, |
| std::move(identify)); |
| } |
| |
| std::shared_ptr<NVMeVolume> |
| NVMeVolume::create(sdbusplus::asio::object_server& objServer, |
| const std::shared_ptr<sdbusplus::asio::connection>& conn, |
| const std::shared_ptr<NVMeSubsystem>& subsys, |
| const NVMeNSIdentify& ns) |
| { |
| auto self = std::shared_ptr<NVMeVolume>( |
| new NVMeVolume(objServer, conn, subsys, ns)); |
| self->init(); |
| return self; |
| } |
| |
| NVMeVolume::~NVMeVolume() |
| { |
| metricStore.reset(); |
| NvmeVolumeBase::emit_removed(); |
| VolumeBase::emit_removed(); |
| objServer.remove_interface(deleteInterface); |
| } |
| |
| void NVMeVolume::erase(VolumeBase::EraseMethod eraseType) |
| { |
| (void)eraseType; |
| // TODO: will need dbus async method handling. |
| throw std::runtime_error("volume erase not yet implemented"); |
| } |
| |
| // Additional methods on Volume that are not relevant. |
| |
| void NVMeVolume::formatLuks([[maybe_unused]] std::vector<uint8_t> password, |
| [[maybe_unused]] VolumeBase::FilesystemType type) |
| { |
| throw std::runtime_error("Method Not Supported"); |
| } |
| |
| void NVMeVolume::lock() |
| { |
| throw std::runtime_error("Method Not Supported"); |
| } |
| |
| void NVMeVolume::unlock([[maybe_unused]] std::vector<uint8_t> password) |
| { |
| throw std::runtime_error("Method Not Supported"); |
| } |
| |
| void NVMeVolume::changePassword( |
| [[maybe_unused]] std::vector<uint8_t> oldPassword, |
| [[maybe_unused]] std::vector<uint8_t> newPassword) |
| { |
| throw std::runtime_error("Method Not Supported"); |
| } |