Commit 002959e1 authored by Eric Cano's avatar Eric Cano
Browse files

Added zeroing helper function and replates memset with it.

Added sg_io_hdr_t wrapper to avoid boilerplate code.
Templated tapeAlertLog structure to make its use safer an added zeroing to it.
Minor documentation clarification.
Updated getTapeAlerts to use new SCSI structures.
Added new function signature: getTapeError.
parent 9ce75af6
......@@ -266,7 +266,8 @@ The SCSI commands and st driver's functions used in previous software (CAStor's
location (a.k.a. block ID).
\item Log select (for clearing compression stats page. The function clear\_compression\_stats
actually does a blanket reset of all statistics. It sets the PCR/SP/PC combination
to 1/0/3, which is strange as the spec indicates 1/0/xx (xx for don't care).
to 1/0/3. The basic SCSI specification states that the value pf PC is not important,
but for the IBM drives, the documentation recommends PC=11b, which we have for all drives.
\item Log sense, to read the compression pages. This is device dependant. The code covers
5 blocks of device types: DAT, DLT-SDLT-LTO, IBM(3490, 3590, 3592), StorageTek RedWood(SD3),
StorageTek(9840, 9940, T10000).
......
......@@ -133,31 +133,22 @@ namespace Tape {
{
/* return vector */
std::vector<std::string> ret;
/* We don't know how many elements we'll get. Prepare a 1kB buffer. */
unsigned char dataBuff[1024];
memset (dataBuff, 0, sizeof (dataBuff));
/* We don't know how many elements we'll get. Prepare a 100 parameters array */
SCSI::Structures::tapeAlertLogPage_t<100> tal;
unsigned char senseBuff[256];
SCSI::Structures::logSenseCDB_t cdb;
cdb.pageCode = SCSI::logSensePages::tapeAlert;
sg_io_hdr_t sgh;
memset(&sgh, 0, sizeof (sgh));
sgh.interface_id = 'S';
sgh.cmdp = (unsigned char *)&cdb;
sgh.cmd_len = sizeof(cdb);
sgh.sbp = senseBuff;
sgh.mx_sb_len = 255;
SCSI::Structures::LinuxSGIO_t sgh;
sgh.setCDB(&cdb);
sgh.setDataBuffer(&tal);
sgh.setSenseBuffer(&senseBuff);
sgh.dxfer_direction = SG_DXFER_FROM_DEV;
sgh.dxferp = dataBuff;
sgh.dxfer_len = sizeof(dataBuff);
sgh.timeout = 30000;
/* Manage both system error and SCSI errors. */
if (-1 == m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh))
throw Tape::Exceptions::Errnum("Failed SG_IO ioctl");
if (SCSI::Status::GOOD != sgh.status)
throw Tape::Exception(std::string("SCSI error in getTapeAlerts: ") +
SCSI::statusToString(sgh.status));
SCSI::Structures::tapeAlertLogPage_t & tal =
*(SCSI::Structures::tapeAlertLogPage_t *) dataBuff;
/* Return the ACTIVE tape alerts (this is indicated but the flag (see
* SSC-4: 8.2.3 TapeAlert log page). As they are simply used for logging,
* return strings. */
......@@ -181,6 +172,12 @@ namespace Tape {
*/
virtual driveStatus getDriveStatus() throw (Exception) { throw Exception("Not implemented"); }
/**
*
* @return string containing the error description
*/
virtual std::string getTapeError() throw (Exception) { throw Exception("Not implemented"); }
virtual ~Drive() {
if(-1 != m_tapeFD)
m_sysWrapper.close(m_tapeFD);
......
......@@ -28,8 +28,11 @@
#include <algorithm>
#include <arpa/inet.h>
#include <string.h>
#include <scsi/sg.h>
#include <climits>
#include "Constants.hh"
#include "../Exception/Exception.hh"
namespace SCSI {
/**
......@@ -41,6 +44,45 @@ namespace SCSI {
* http://hackipedia.org/Hardware/SCSI/Stream%20Commands/SCSI%20Stream%20Commands%20-%203.pdf
*/
namespace Structures {
/**
* Helper template to zero a structure. Small boilerplate reduction.
* Should not be used with classes with virtual tables! With a zeroed
* out virtual table pointer, this will be detected soon enough.
* @param s pointer the struct/class.
*/
template <typename C>
void zeroStruct(C * s) {
memset (s, 0, sizeof(C));
}
/**
* Class wrapping around Linux' SG_IO struct, providing
* zeroing and automatic filling up for the mandatory structures
* (cdb, databuffer, sense buffer, magic 'S', and default timeout).
* Make it look like a bare sg_io_hdr_t when using & operator.
* Another little boilerplate killer.
*/
class LinuxSGIO_t: public sg_io_hdr_t {
public:
LinuxSGIO_t() { zeroStruct(this); interface_id = 'S'; timeout = 30000; }
template <typename T>
void setCDB(T * cdb) { cmdp = (unsigned char *)cdb; cmd_len = sizeof(T); }
template <typename T>
void setSenseBuffer(T * senseBuff) throw (Tape::Exception)
{
if (sizeof(T) > UCHAR_MAX)
throw Tape::Exception("sense structure too big in LinuxSGIO_t::setSense");
sb_len_wr = (unsigned char) sizeof(T);
sbp = (unsigned char *)senseBuff;
}
template <typename T>
void setDataBuffer(T * dataBuff) { dxferp = dataBuff; dxfer_len = sizeof (T); }
sg_io_hdr_t * operator & () { return (sg_io_hdr_t *) this; }
};
/**
* Helper function to deal with endianness.
......@@ -79,7 +121,7 @@ namespace SCSI {
char allocationLength[2];
unsigned char control;
inquiryCDB_t() { memset(this, 0, sizeof(*this)); opCode = SCSI::Commands::INQUIRY; }
inquiryCDB_t() { zeroStruct(this); opCode = SCSI::Commands::INQUIRY; }
};
/**
......@@ -170,7 +212,7 @@ namespace SCSI {
unsigned char control; // CONTROL
logSelectCDB_t() {
memset(this, 0, sizeof(*this));
zeroStruct(this);
opCode = SCSI::Commands::LOG_SELECT;
}
};
......@@ -196,7 +238,7 @@ namespace SCSI {
unsigned char control;
logSenseCDB_t() { memset(this, 0, sizeof(*this)); opCode = SCSI::Commands::LOG_SENSE; }
logSenseCDB_t() { zeroStruct(this); opCode = SCSI::Commands::LOG_SENSE; }
};
class tapeAlertLogParameter_t {
......@@ -219,6 +261,7 @@ namespace SCSI {
/**
* Tape alert log mage, returned by LOG SENSE. Defined in SSC-3, section 8.2.3 TapeAler log page.
*/
template <int n>
class tapeAlertLogPage_t {
public:
unsigned char pageCode : 6;
......@@ -228,13 +271,19 @@ namespace SCSI {
char pageLength[2];
tapeAlertLogParameter_t parameters [1];
tapeAlertLogParameter_t parameters [n];
/**
* Utility function computing the number of parameters.
* @return number of parameters.
*/
int parameterNumber() { return SCSI::Structures::toU16(pageLength) / sizeof (tapeAlertLogPage_t); }
int parameterNumber() throw (Tape::Exception) {
int numFromLength = SCSI::Structures::toU16(pageLength) / sizeof (tapeAlertLogPage_t);
if (numFromLength > n)
throw Tape::Exception("In tapeAlertLogPage_t::parameterNumber: too many parameters from device");
return numFromLength;
}
tapeAlertLogPage_t() { zeroStruct(this); }
};
template <size_t n>
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment