Skip to content

Commit

Permalink
Move more code (device statistics) to StorageDevice class (#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
uweseimet committed Aug 23, 2024
1 parent 3c034f6 commit 2967c8f
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 123 deletions.
119 changes: 8 additions & 111 deletions cpp/devices/disk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ bool Disk::Init(const param_map &params)
{
Seek6();
});
AddCommand(scsi_command::cmd_start_stop, [this]
{
StartStopUnit();
});
AddCommand(scsi_command::cmd_prevent_allow_medium_removal, [this]
{
PreventAllowMediumRemoval();
});
AddCommand(scsi_command::cmd_read_capacity10, [this]
{
ReadCapacity10();
Expand Down Expand Up @@ -130,20 +122,6 @@ void Disk::CleanUp()
StorageDevice::CleanUp();
}

void Disk::Dispatch(scsi_command cmd)
{
// Media changes must be reported on the next access, i.e. not only for TEST UNIT READY
if (cmd != scsi_command::cmd_inquiry && cmd != scsi_command::cmd_request_sense && IsMediumChanged()) {
assert(IsRemovable());

SetMediumChanged(false);

throw scsi_exception(sense_key::unit_attention, asc::not_ready_to_ready_change);
}

StorageDevice::Dispatch(cmd);
}

void Disk::ValidateFile()
{
StorageDevice::ValidateFile();
Expand Down Expand Up @@ -307,71 +285,13 @@ void Disk::ReadWriteLong(uint64_t sector, uint32_t length, bool write)
DataOutPhase(length);
}
else {
++sector_read_count;
UpdateReadCount(1);

GetController()->SetCurrentLength(length);
DataInPhase(linux_cache->ReadLong(GetController()->GetBuffer(), sector, length));
}
}


void Disk::StartStopUnit()
{
const bool start = GetController()->GetCdbByte(4) & 0x01;
const bool load = GetController()->GetCdbByte(4) & 0x02;

if (load) {
LogTrace(start ? "Loading medium" : "Ejecting medium");
}
else {
LogTrace(start ? "Starting unit" : "Stopping unit");

SetStopped(!start);
}

if (!start) {
// Look at the eject bit and eject if necessary
if (load) {
if (IsLocked()) {
// Cannot be ejected because it is locked
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}

// Eject
if (!Eject(false)) {
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}
}
else {
FlushCache();
}
}
else if (load && !last_filename.empty()) {
SetFilename(last_filename);
if (!ReserveFile()) {
last_filename.clear();
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}

SetMediumChanged(true);
}

StatusPhase();
}

void Disk::PreventAllowMediumRemoval()
{
CheckReady();

const bool lock = GetController()->GetCdbByte(4) & 0x01;

LogTrace(lock ? "Locking medium" : "Unlocking medium");

SetLocked(lock);

StatusPhase();
}

void Disk::SynchronizeCache()
{
FlushCache();
Expand All @@ -394,18 +314,9 @@ void Disk::ReadDefectData10() const

bool Disk::Eject(bool force)
{
const bool status = PrimaryDevice::Eject(force);
const bool status = StorageDevice::Eject(force);
if (status) {
FlushCache();
cache.reset();

last_filename = GetFilename();

// The image file for this drive is not in use anymore
UnreserveFile();

sector_read_count = 0;
sector_write_count = 0;
}

return status;
Expand Down Expand Up @@ -756,7 +667,8 @@ int Disk::ReadData(span<uint8_t> buf)
}

next_sector += sector_transfer_count;
sector_read_count += sector_transfer_count;

UpdateReadCount(sector_transfer_count);

return GetBlockSizeInBytes() * sector_transfer_count;
}
Expand All @@ -776,7 +688,7 @@ int Disk::WriteData(span<const uint8_t> buf, scsi_command command)
throw scsi_exception(sense_key::medium_error, asc::write_fault);
}

++sector_write_count;
UpdateWriteCount(1);

return length;
}
Expand All @@ -787,7 +699,8 @@ int Disk::WriteData(span<const uint8_t> buf, scsi_command command)
}

next_sector += sector_transfer_count;
sector_write_count += sector_transfer_count;

UpdateWriteCount(sector_transfer_count);

return GetBlockSizeInBytes() * sector_transfer_count;
}
Expand Down Expand Up @@ -955,7 +868,7 @@ tuple<bool, uint64_t, uint32_t> Disk::CheckAndGetStartAndCount(access_mode mode)

vector<PbStatistics> Disk::GetStatistics() const
{
vector<PbStatistics> statistics = PrimaryDevice::GetStatistics();
vector<PbStatistics> statistics = StorageDevice::GetStatistics();

// Enrich cache statistics with device information before adding them to device statistics
if (cache) {
Expand All @@ -966,21 +879,5 @@ vector<PbStatistics> Disk::GetStatistics() const
}
}

PbStatistics s;
s.set_id(GetId());
s.set_unit(GetLun());

s.set_category(PbStatisticsCategory::CATEGORY_INFO);

s.set_key(SECTOR_READ_COUNT);
s.set_value(sector_read_count);
statistics.push_back(s);

if (!IsReadOnly()) {
s.set_key(SECTOR_WRITE_COUNT);
s.set_value(sector_write_count);
statistics.push_back(s);
}

return statistics;
}
12 changes: 0 additions & 12 deletions cpp/devices/disk.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ class Disk : public StorageDevice, public ScsiBlockCommands
bool Init(const param_map&) override;
void CleanUp() override;

void Dispatch(scsi_command) override;

bool Eject(bool) override;

int WriteData(span<const uint8_t>, scsi_command) override;
Expand Down Expand Up @@ -91,8 +89,6 @@ class Disk : public StorageDevice, public ScsiBlockCommands

// Commands covered by the SCSI specifications (see https://www.t10.org/drafts.htm)

void StartStopUnit();
void PreventAllowMediumRemoval();
void SynchronizeCache();
void ReadDefectData10() const;
virtual void Read6()
Expand Down Expand Up @@ -151,12 +147,4 @@ class Disk : public StorageDevice, public ScsiBlockCommands
uint64_t next_sector = 0;

uint32_t sector_transfer_count = 0;

uint64_t sector_read_count = 0;
uint64_t sector_write_count = 0;

string last_filename;

static constexpr const char *SECTOR_READ_COUNT = "sector_read_count";
static constexpr const char *SECTOR_WRITE_COUNT = "sector_write_count";
};
129 changes: 129 additions & 0 deletions cpp/devices/storage_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,118 @@ StorageDevice::StorageDevice(PbDeviceType type, scsi_level level, int lun, bool
SetStoppable(true);
}

bool StorageDevice::Init(const param_map &params)
{
ModePageDevice::Init(params);

AddCommand(scsi_command::cmd_start_stop, [this]
{
StartStopUnit();
});
AddCommand(scsi_command::cmd_prevent_allow_medium_removal, [this]
{
PreventAllowMediumRemoval();
});

return true;
}

void StorageDevice::CleanUp()
{
UnreserveFile();

ModePageDevice::CleanUp();
}

void StorageDevice::Dispatch(scsi_command cmd)
{
// Media changes must be reported on the next access, i.e. not only for TEST UNIT READY
if (cmd != scsi_command::cmd_inquiry && cmd != scsi_command::cmd_request_sense && IsMediumChanged()) {
assert(IsRemovable());

SetMediumChanged(false);

throw scsi_exception(sense_key::unit_attention, asc::not_ready_to_ready_change);
}

ModePageDevice::Dispatch(cmd);
}

void StorageDevice::StartStopUnit()
{
const bool start = GetController()->GetCdbByte(4) & 0x01;
const bool load = GetController()->GetCdbByte(4) & 0x02;

if (load) {
LogTrace(start ? "Loading medium" : "Ejecting medium");
}
else {
LogTrace(start ? "Starting unit" : "Stopping unit");

SetStopped(!start);
}

if (!start) {
// Look at the eject bit and eject if necessary
if (load) {
if (IsLocked()) {
// Cannot be ejected because it is locked
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}

// Eject
if (!Eject(false)) {
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}
}
else {
FlushCache();
}
}
else if (load && !last_filename.empty()) {
SetFilename (last_filename);
if (!ReserveFile()) {
last_filename.clear();
throw scsi_exception(sense_key::illegal_request, asc::load_or_eject_failed);
}

SetMediumChanged(true);
}

StatusPhase();
}

void StorageDevice::PreventAllowMediumRemoval()
{
CheckReady();

const bool lock = GetController()->GetCdbByte(4) & 0x01;

LogTrace(lock ? "Locking medium" : "Unlocking medium");

SetLocked(lock);

StatusPhase();
}

bool StorageDevice::Eject(bool force)
{
const bool status = ModePageDevice::Eject(force);
if (status) {
FlushCache();

last_filename = GetFilename();

// The image file for this device is not in use anymore
UnreserveFile();

block_read_count = 0;
block_write_count = 0;
}

return status;
}

bool StorageDevice::SetBlockSizeInBytes(uint32_t size)
{
if (!supported_block_sizes.contains(size) && configured_block_size != size) {
Expand Down Expand Up @@ -120,3 +225,27 @@ off_t StorageDevice::GetFileSize() const
throw io_exception("Can't get size of '" + filename.string() + "': " + e.what());
}
}

vector<PbStatistics> StorageDevice::GetStatistics() const
{
vector<PbStatistics> statistics = ModePageDevice::GetStatistics();

PbStatistics s;
s.set_id(GetId());
s.set_unit(GetLun());

s.set_category(PbStatisticsCategory::CATEGORY_INFO);

s.set_key(BLOCK_READ_COUNT);
s.set_value(block_read_count);
statistics.push_back(s);

if (!IsReadOnly()) {
s.set_key(BLOCK_WRITE_COUNT);
s.set_value(block_write_count);
statistics.push_back(s);
}

return statistics;
}

Loading

0 comments on commit 2967c8f

Please sign in to comment.