Do media checks on getting next block encryption status (#74)

* Do media check before getting NBES and allow getting status without media
* Supress error from BLANK CHECK sense when querying next block encryption status
This commit is contained in:
James Wilson
2022-05-18 22:27:11 +02:00
committed by GitHub
parent 8caaf85fbb
commit a7a7c4750c
3 changed files with 53 additions and 15 deletions
+16 -5
View File
@@ -200,7 +200,7 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt, boo
}
static void showDriveStatus(const std::string& tapeDrive, bool detail) {
alignas(4) scsi::page_buffer buffer;
alignas(4) scsi::page_buffer buffer {};
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
@@ -281,7 +281,7 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
}
static void showVolumeStatus(const std::string& tapeDrive) {
alignas(4) scsi::page_buffer buffer;
alignas(4) scsi::page_buffer buffer {};
scsi::get_nbes(tapeDrive, buffer, sizeof(buffer));
auto& opt {reinterpret_cast<const scsi::page_nbes&>(buffer)};
@@ -420,8 +420,19 @@ int main(int argc, const char **argv) {
inquiryDrive(tapeDrive);
}
showDriveStatus(tapeDrive, detail);
if (detail) {
showVolumeStatus(tapeDrive);
if (detail && scsi::is_device_ready(tapeDrive)) {
try {
showVolumeStatus(tapeDrive);
} catch (const scsi::scsi_error& err) {
// #71: ignore BLANK CHECK sense key that some drives may return
// during media access check in getting NBES
auto sense_key {
err.get_sense().flags & scsi::sense_data::flags_sense_key_mask
};
if (sense_key != scsi::sense_data::blank_check) {
throw;
}
}
}
exit(EXIT_SUCCESS);
} catch (const scsi::scsi_error& err) {
@@ -495,7 +506,7 @@ int main(int argc, const char **argv) {
key, key_name, rdmc, ckod)};
scsi::write_sde(tapeDrive, sde_buffer.get());
alignas(4) scsi::page_buffer buffer;
alignas(4) scsi::page_buffer buffer {};
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
+23 -10
View File
@@ -83,7 +83,7 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
std::size_t dxfer_len, scsi_direction direction)
{
#if defined(OS_LINUX)
unique_fd fd {open(device.c_str(), O_RDONLY)};
unique_fd fd {open(device.c_str(), O_RDONLY | O_NDELAY)};
if (!fd) {
std::ostringstream oss;
oss << "Cannot open device " << device;
@@ -146,6 +146,19 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
namespace scsi {
bool is_device_ready(const std::string& device)
{
const std::uint8_t test_unit_ready_cmd[6] {};
try {
scsi_execute(device, test_unit_ready_cmd, sizeof(test_unit_ready_cmd),
nullptr, 0u, scsi_direction::from_device);
return true;
} catch (const scsi::scsi_error& err) {
return false;
}
}
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length)
{
const std::uint8_t spin_des_command[] {
@@ -266,31 +279,31 @@ void write_sde(const std::string& device, const std::uint8_t *sde_buffer)
void print_sense_data(std::ostream& os, const sense_data& sd) {
os << std::left << std::setw(25) << "Sense Code: ";
auto sense_key {static_cast<unsigned int>(sd.flags & sense_data::flags_sense_key_mask)};
auto sense_key {sd.flags & sense_data::flags_sense_key_mask};
switch (sense_key) {
case 0u:
case sense_data::no_sense:
os << "No specific error";
break;
case 2u:
case sense_data::not_ready:
os << "Device not ready";
break;
case 3u:
case sense_data::medium_error:
os << "Medium Error";
break;
case 4u:
case sense_data::hardware_error:
os << "Hardware Error";
break;
case 5u:
case sense_data::illegal_request:
os << "Illegal Request";
break;
case 6u:
case sense_data::unit_attention:
os << "Unit Attention";
break;
case 7u:
case sense_data::data_protect:
os << "Data protect";
break;
case 8u:
case sense_data::blank_check:
os << "Blank tape";
break;
}
+14
View File
@@ -285,6 +285,17 @@ struct __attribute__((packed)) sense_data {
std::uint8_t field_replaceable_unit_code;
std::uint8_t sense_key_specific[3];
std::uint8_t additional_sense_bytes[];
static constexpr std::byte no_sense {0u};
static constexpr std::byte recovered_error {1u};
static constexpr std::byte not_ready {2u};
static constexpr std::byte medium_error {3u};
static constexpr std::byte hardware_error {4u};
static constexpr std::byte illegal_request {5u};
static constexpr std::byte unit_attention {6u};
static constexpr std::byte data_protect {7u};
static constexpr std::byte blank_check {8u};
static constexpr auto maximum_size {252u}; // per SPC-5
};
static_assert(sizeof(sense_data) == 18u);
@@ -321,6 +332,9 @@ std::vector<const kad *> read_page_kads(const Page& page)
return v;
}
// Check if a tape is loaded
bool is_device_ready(const std::string& device);
// Get SCSI inquiry data from device
inquiry_data get_inquiry(const std::string& device);
// Get data encryption status page
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length);