Commit cbf9b705 authored by Eric Cano's avatar Eric Cano
Browse files

TPSRV-6:

Added a helper function to set SCSI 16 bits values.
Added test for Tape::Drive::getTapeAlerts
Fixed Tape::Drive::getTapeAlerts
Removed the -O2 from the compilation options: debugging was sometimes confusing, and compilation is now faster.
Also removed optimisation from rpm build.
parent 103b0f0c
......@@ -45,7 +45,7 @@ LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
###########################################################################
# compiler options
###########################################################################
set (CMAKE_CXX_FLAGS "-g3 -Wall -Werror -pedantic -O2")
set (CMAKE_CXX_FLAGS "-g3 -Wall -Werror -pedantic")
###########################################################################
# dependancies
......
......@@ -198,7 +198,8 @@ throw (Tape::Exception) {
/**
* Get tape alert information from the drive. There is a quite long list of possible tape alerts.
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface
* They are described in SSC-4, section 4.2.20: TapeAlert application client interface.
* Section is 4.2.17 in SSC-3.
* @return list of tape alerts descriptions. They are simply used for logging.
*/
std::vector<std::string> Tape::Drive::getTapeAlerts() throw (Tape::Exception) {
......@@ -210,9 +211,11 @@ std::vector<std::string> Tape::Drive::getTapeAlerts() throw (Tape::Exception) {
SCSI::Structures::senseData_t<255> senseBuff;
SCSI::Structures::logSenseCDB_t cdb;
cdb.pageCode = SCSI::logSensePages::tapeAlert;
cdb.PC = 0x01; // Current Comulative Values
SCSI::Structures::LinuxSGIO_t sgh;
sgh.setCDB(&cdb);
sgh.setDataBuffer(&tal);
SCSI::Structures::setU16(cdb.allocationLength, sizeof(tal));
sgh.setSenseBuffer(&senseBuff);
sgh.dxfer_direction = SG_DXFER_FROM_DEV;
/* Manage both system error and SCSI errors. */
......
......@@ -322,6 +322,56 @@ TEST(TapeDrive, getCompressionAndClearCompressionStats) {
}
}
}
}
}
TEST(TapeDrive, getTapeAlerts) {
/**
* "Local function" allowing the test to be run twice (for SLC5 and then for
* SLC6).
*/
struct {
void operator() (Tape::System::mockWrapper & sysWrapper) {
/* We expect the following calls: */
EXPECT_CALL(sysWrapper, opendir(_)).Times(3);
EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
EXPECT_CALL(sysWrapper, closedir(_)).Times(3);
EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
EXPECT_CALL(sysWrapper, open(_, _)).Times(14);
EXPECT_CALL(sysWrapper, read(_, _, _)).Times(20);
EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(2);
EXPECT_CALL(sysWrapper, close(_)).Times(14);
EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
EXPECT_CALL(sysWrapper, stat(_, _)).Times(7);
/* Test: detect devices, then open the device files */
SCSI::DeviceVector dl(sysWrapper);
for (std::vector<SCSI::DeviceInfo>::iterator i = dl.begin();
i != dl.end(); i++) {
if (SCSI::Types::tape == i->type) {
Tape::Drive drive(*i, sysWrapper);
EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t*>())).Times(1);
std::vector<std::string> alerts = drive.getTapeAlerts();
ASSERT_EQ(3U, alerts.size());
ASSERT_FALSE(alerts.end() ==
find(alerts.begin(), alerts.end(),
std::string("Unexpected tapeAlert code: 0x41")));
ASSERT_FALSE(alerts.end() == find(alerts.begin(), alerts.end(),
std::string("Obsolete tapeAlert code: 0x28")));
ASSERT_FALSE(alerts.end() == find(alerts.begin(), alerts.end(),
std::string("Forced eject")));
}
}
}
} test_functor;
/* Prepare the test harness */
Tape::System::mockWrapper sysWrapper;
sysWrapper.fake.setupSLC5();
sysWrapper.delegateToFake();
test_functor(sysWrapper);
}
}
......@@ -148,6 +148,16 @@ namespace SCSI {
return htonl(t);
}
/**
* Helper function setting in place a 16 bits SCSI number from a value
* expressed in the local endianness.
* @param t pointer to the char array at the 16 bits value position.
* @param val the value.
*/
inline void setU16(unsigned char(& t)[2], uint16_t val) {
*((uint16_t *) t) = htons(val);
}
/**
* Helper function to deal with endianness.
* @param t byte array in SCSI order representing a 16 bits number
......
......@@ -253,6 +253,8 @@ int Tape::System::stDeviceFile::ioctlLogSense(sg_io_hdr_t * sgio_h) {
return logSenseDataCompression32h(sgio_h);
case SCSI::logSensePages::blockBytesTransferred:
return logSenseBlockBytesTransferred(sgio_h);
case SCSI::logSensePages::tapeAlert:
return logSenseTapeAlerts(sgio_h);
}
errno = EINVAL;
return -1;
......@@ -366,6 +368,49 @@ int Tape::System::stDeviceFile::logSenseBlockBytesTransferred(sg_io_hdr_t * sgio
return 0;
}
int Tape::System::stDeviceFile::logSenseTapeAlerts(sg_io_hdr_t* sgio_h) {
size_t remaining = sgio_h->dxfer_len;
/* Truncation of any field should yield an error */
if (remaining < (4 + 320)) {
errno = EINVAL;
return -1;
}
/* Header as-is from mhvtl. */
unsigned char * data = (unsigned char *) sgio_h->dxferp;
data[0] = 0x2eU;
/* 145h bytes, with parameters of 5 bytes means 65 parameters */
data[2] = 0x1U;
data[3] = 0x45U;
data += 4; remaining -= 4;
/* This array was extracted from p/x in gdb of the tape alert log page from
* mhvtl, then processed through:
* cat mhvtlAlerts.txt | tr -d "\n" | perl -p -e 's/\},/}\n/g' | grep parameterCode |
* perl -e 'while (<>) { if ( /\{\s*(0x[[:xdigit:]]+),\s*(0x[[:xdigit:]]+)\}/ ) { print (hex($1) * 256 + hex($2)); print ", " } }'*/
/* We also add an out-of-range 65 */
uint16_t parameterCodes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65 };
size_t i = 0;
while (remaining > 5 && i < 65) {
/* small gymnastic to turn a bare buffer into a SCSI u16 storage */
struct u16wrap { unsigned char u16[2]; };
struct u16wrap * s((struct u16wrap *) &(data[0]));
SCSI::Structures::setU16(s->u16, parameterCodes[i]);
data[2] = 0U;
data[3] = 1U;
data[4] = 0U; /* TODO: at least some parameters should get set */
switch (parameterCodes[i]) {
case 0x28:
case 0x10:
case 65:
data[4] |= 1; /* Set flag */
}
i++; data += 5; remaining -=5;
}
return 0;
}
int Tape::System::stDeviceFile::ioctlModSense6(sg_io_hdr_t * sgio_h) {
if (SG_DXFER_FROM_DEV != sgio_h->dxfer_direction) {
errno = EINVAL;
......
......@@ -188,6 +188,16 @@ namespace System {
* -1 with appropriate errno if an error occurred.
*/
int logSenseBlockBytesTransferred(sg_io_hdr_t * sgio_h);
/**
* This function replies with a pre-cooked error record. As with the real devices,
* many parameter codes get reported with a flag set to 0, and a few will
* show up with the flag set.
* @param sgio_h The pointer to the sg_io_hdr_t structure with
* ioctl call data
* @return Returns 0 in success and
* -1 with appropriate errno if an error occurred.
*/
int logSenseTapeAlerts(sg_io_hdr_t * sgio_h);
};
class tapeGenericDeviceFile: public vfsFile {
......
......@@ -45,8 +45,8 @@ test -e $RPM_BUILD_ROOT && rm -r $RPM_BUILD_ROOT
mkdir -p build
cd build
cmake ../ -DRELEASE=%{release} -DCMAKE_BUILD_TYPE=RelWithDebInfo
%{__make} %{_smp_mflags} all doxygen TapeServer_pdf
cmake ../ -DRELEASE=%{release} -DCMAKE_BUILD_TYPE=Debug
%{__make} %{_smp_mflags} all doxygen TapeServer_pdf VERBOSE=1
%install
cd build
......
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