blob: b00a900c40f8054447dbcc7d1129818e1fca8f60 [file] [log] [blame]
#pragma once
#include "NVMeBasic.hpp"
#include "NVMeController.hpp"
#include "NVMeDrive.hpp"
#include "NVMePlugin.hpp"
#include "NVMeProgress.hpp"
#include "NVMeSensor.hpp"
#include "NVMeStorage.hpp"
#include "NVMeUtil.hpp"
#include "Utils.hpp"
#include <cstdint>
class NVMeVolume;
class NVMeCreateVolumeProgress;
#ifdef NVME_UNIT_TEST
class NVMeTest;
#endif
class NVMeSubsystem :
public std::enable_shared_from_this<NVMeSubsystem>,
public NVMeStorage
{
public:
static std::shared_ptr<NVMeSubsystem>
create(boost::asio::io_context& io,
sdbusplus::asio::object_server& objServer,
const std::shared_ptr<sdbusplus::asio::connection>& conn,
const std::string& path, const std::string& name,
const SensorData& configData, NVMeIntf intf);
~NVMeSubsystem() override;
void start();
void stop();
/** @brief Returns the dbus path for a given volume.
*
* @param[in] nsid - The NSID of the volume
*
* @return path[std::string] - The dbus path for the volume.
*/
std::string volumePath(uint32_t nsid) const;
/**
* @brief delete given namespace from the nvme device and nvme daemon,
* throws on error
*/
void deleteVolume(boost::asio::yield_context yield,
const std::shared_ptr<NVMeVolume>& volume);
std::vector<uint32_t> attachedVolumes(uint16_t ctrlId) const;
/**
* @brief Attach the namespace to controller, throws std::runtime_error on
* failure
*/
void attachCtrlVolume(uint16_t ctrlId, uint32_t nsid);
/**
* @brief Detach the namespace from controller, throws std::runtime_error on
* failure
*/
void detachCtrlVolume(uint16_t ctrlId, uint32_t nsid);
void detachAllCtrlVolume(uint32_t nsid);
std::shared_ptr<NVMeVolume>
getVolume(const sdbusplus::message::object_path& volPath) const;
void startSanitize(const NVMeSanitizeParams& params,
std::function<void(nvme_ex_ptr ex)>&& submitCb);
void sanitizeStatus(
std::function<void(nvme_ex_ptr ex, bool inProgress, bool failed,
bool completed, uint16_t sstat, uint16_t sprog,
uint32_t scdw10)>&& cb);
const std::string path;
NVMeSubsystem(boost::asio::io_context& io,
sdbusplus::asio::object_server& objServer,
const std::shared_ptr<sdbusplus::asio::connection>& conn,
const std::string& path, const std::string& name,
const SensorData& configData, NVMeIntf intf);
void init();
const std::string& getName() const
{
return name;
}
#if defined NVME_UNIT_TEST
// allow the test fixture change the settings for subsystem
friend class NVMeTest;
#endif
private:
friend class NVMePlugin;
template <nvme_identify_cns CNS, class ClockType>
friend class IdentifyMetric;
boost::asio::io_context& io;
sdbusplus::asio::object_server& objServer;
std::shared_ptr<sdbusplus::asio::connection> conn;
std::string name;
SensorData config;
NVMeIntf nvmeIntf;
/*
* stateDiagram
* [*] --> Stop
* Stop --> Intiatilzing
* Intiatilzing --> Start
* Intiatilzing --> Aborting
* Start --> Terminating
* Aborting --> Terminating
* Terminating --> Stop
*/
enum class Status : uint8_t
{
Stop,
Intiatilzing,
Aborting,
Start,
Terminating,
};
Status status;
// plugin
std::shared_ptr<NVMePlugin> plugin;
/* thermal sensor for the subsystem */
std::shared_ptr<NVMeSensor> ctemp;
std::shared_ptr<boost::asio::steady_timer> ctempTimer;
std::chrono::milliseconds pollingInterval = std::chrono::milliseconds(1000);
/* Begin of patch context
*
*
*
*/
/*
*
*
* End of patch context
*/
/*
Drive interface: xyz.openbmc_project.Inventory.Item.Drive
*/
std::shared_ptr<NVMeDrive> drive;
// map from cntrlid to a pair of {controller, controller_plugin}
std::map<uint16_t, std::pair<std::shared_ptr<NVMeController>,
std::shared_ptr<NVMeControllerPlugin>>>
controllers;
/*
map of nsid to volumes
*/
std::map<uint32_t, std::shared_ptr<NVMeVolume>> volumes;
/*
* volumes attached to controllers
*/
std::map<uint16_t, std::set<uint32_t>> attached;
/*
In-progress or completed create operations
*/
std::unordered_map<std::string, std::shared_ptr<NVMeCreateVolumeProgress>>
createProgress;
// controller to use for NVMe operations. Is a member of the controllers
// map. Access this through getPrimaryController() to test for nullness.
std::shared_ptr<NVMeControllerEnabled> primaryController;
std::shared_ptr<sdbusplus::asio::dbus_interface> assocIntf;
void createAssociation();
void updateAssociation();
std::vector<Association> makeAssociation() const;
// make the subsystem functional/functional be enabling/disabling the
// storage controller, namespaces and thermal sensors.
void markFunctional(bool toggle);
// mark the availability of the Storage device.
void markAvailable(bool toggle);
// may throw NVMeError if no controller is available
std::shared_ptr<NVMeControllerEnabled> getPrimaryController() const;
sdbusplus::message::object_path
createVolume(boost::asio::yield_context yield, uint64_t size,
size_t lbaFormat, bool metadataAtEnd) override;
// callback when drive completes. not called in dbus method context.
void createVolumeFinished(const std::string& progId, const nvme_ex_ptr& ex,
NVMeNSIdentify ns);
void addIdentifyNamespace(boost::asio::yield_context yield, uint32_t nsid);
// fill DBus object for Drive, throws on failure
void fillDrive(boost::asio::yield_context yield);
// update all namespaces in the subsystem, throws on failure
void updateVolumes(boost::asio::yield_context yield);
// removes state associated with the volume. Does not manipulate the drive.
// throws on error
void forgetVolume(const std::shared_ptr<NVMeVolume>& volume);
// adds state associated with the volume. Does not create a volume.
// may throw if the volume exists.
std::shared_ptr<NVMeVolume> addVolume(const NVMeNSIdentify& ns);
// query the supported LBA formats from identify ns, throws on failure
void querySupportedFormats(boost::asio::yield_context yield);
// a counter to skip health poll when NVMe subsystem becomes Unavailable
unsigned unavailableCount = 0;
unsigned unavailableMaxCount = 60;
// process Secondary controller and start controllers and the associated
// Plugin
void processSecondaryControllerList(nvme_secondary_ctrl_list* secCntlrList);
};