blob: 4c429a524d4b62a0de824099887a0b07721d7aa0 [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// brillo::DevmapperTask is a lower level device-mapper construct which denotes
// an operation on a dm target. This class is mostly meant to be used as a
// building block for the simpler, application-friendly brillo::DeviceMapper
// interface.
#ifndef LIBBRILLO_BRILLO_BLKDEV_UTILS_DEVICE_MAPPER_TASK_H_
#define LIBBRILLO_BRILLO_BLKDEV_UTILS_DEVICE_MAPPER_TASK_H_
#include <libdevmapper.h>
#include <memory>
#include <string>
#include <brillo/secure_blob.h>
namespace brillo {
using DmTaskPtr = std::unique_ptr<dm_task, void (*)(dm_task*)>;
// The device mapper driver maintains versions for both its kernel drivers and
// for each specific target. Specifically, version numbers are used to signal
// whether a particular feature is supported, either by the kernel driver or
// by a specific target.
struct DeviceMapperVersion {
uint32_t major;
uint32_t minor;
uint32_t patchlevel;
bool operator<(const DeviceMapperVersion& rhs) const {
return std::tie(major, minor, patchlevel) <
std::tie(rhs.major, rhs.minor, rhs.patchlevel);
}
};
// Abstract class to manage DM devices.
// This class implements the bare minimum set of functions
// required to create/remove DM devices. DevmapperTask is the equivalent
// of a command to the device mapper to set/get targets associated with a
// logical DM device, but omits, for now, finer-grained commands.
// A target represents a segment of a DM device.
//
// The abstract class is strictly based on the dm_task_* functions
// from libdevmapper, but the interface provides sufficient flexibility
// for other implementations (eg. invoking dmsetup) or testing facades.
//
// The task type enum is defined in libdevmapper.h: for simplicity, the same
// enum types are reused in fake implementations of DevmapperTask.
// The following task types have been tested with DeviceMapper functions:
// - DM_DEVICE_CREATE: used in DeviceMapper::Setup.
// - DM_DEVICE_REMOVE: used in DeviceMapper::Remove.
// - DM_DEVICE_TABLE: used in DeviceMapper::GetTable and
// DeviceMapper::WipeTable.
// - DM_DEVICE_RELOAD: used in DeviceMapper::WipeTable.
// - DM_GET_TARGET_VERSION: used in DeviceMapper::GetVersion.
// - DM_DEVICE_TARGET_MSG: used in Devicemapper::Message
// - DM_DEVICE_SUSPEND: used in DeviceMapper::Suspend.
// - DM_DEVICE_RESUME: used in DeviceMapper::Resume.
class DevmapperTask {
public:
virtual ~DevmapperTask() = default;
// Sets device name for the command.
virtual bool SetName(const std::string& name) = 0;
// Sets the block to device to be read-only.
virtual bool SetReadOnly() = 0;
// Checks if the device has an open reference count.
virtual bool NoOpenCount() = 0;
// Sets message to a command.
virtual bool SetMessage(const std::string& msg) = 0;
// Adds a target to the command. Should be followed by a Run();
// Parameters:
// start: start of target in device.
// sectors: number of sectors in the target.
// type: type of the target.
// parameters: target parameters.
virtual bool AddTarget(uint64_t start,
uint64_t sectors,
const std::string& type,
const SecureBlob& parameters) = 0;
// Gets the next target from the command.
// Returns true while another target exists.
// If no target exist for the device, GetNextTarget sets all
// parameters to 0 and returns false.
//
// Parameters:
// start: start of target in device.
// sectors: number of sectors in the target.
// type: type of the target.
// parameters: target parameters.
virtual bool GetNextTarget(uint64_t* start,
uint64_t* sectors,
std::string* type,
SecureBlob* parameters) = 0;
// Run the task.
// Returns true if the task succeeded.
//
// Parameters:
// udev_sync: Enable/Disable udev_synchronization. Defaults to false.
// Enable only for tasks that create/remove/rename files to
// prevent both udevd and libdevmapper from attempting to
// add or remove files.
virtual bool Run(bool udev_sync = false) = 0;
// Returns version for the current task's target type. Each device
// mapper target maintains a separate version in source that acts as an
// indicator of whether a feature (eg. keyring support for dm-crypt) is
// supported. On failure, return {0, 0, 0} which disallows any
// version-specific features.
virtual DeviceMapperVersion GetVersion() = 0;
// Set deferred removal for the task. If set to true, the device is removed
// once the last user closes it.
// Deferred removal is supported from kernel 3.13 onwards.
// Returns true if the flag is successfully set.
virtual bool SetDeferredRemove() = 0;
};
// Libdevmapper implementation for DevmapperTask.
class DevmapperTaskImpl : public DevmapperTask {
public:
explicit DevmapperTaskImpl(int type);
~DevmapperTaskImpl() override = default;
bool SetName(const std::string& name) override;
bool SetReadOnly() override;
bool NoOpenCount() override;
bool SetMessage(const std::string& msg) override;
bool AddTarget(uint64_t start,
uint64_t sectors,
const std::string& target,
const SecureBlob& parameters) override;
bool GetNextTarget(uint64_t* start,
uint64_t* sectors,
std::string* target,
SecureBlob* parameters) override;
bool Run(bool udev_sync = true) override;
DeviceMapperVersion GetVersion() override;
bool SetDeferredRemove() override;
private:
DmTaskPtr task_;
void* next_target_ = nullptr;
};
} // namespace brillo
#endif // LIBBRILLO_BRILLO_BLKDEV_UTILS_DEVICE_MAPPER_TASK_H_