Commit 22781690 authored by Julien Leduc's avatar Julien Leduc
Browse files

00040-CASTOR-5279-Logical-Block-Protection-support-in-the-.patch...

00040-CASTOR-5279-Logical-Block-Protection-support-in-the-.patch a8903b0b6a081dc47546e4f07a2f8e27f1a774f1
parent 3e140143
......@@ -129,6 +129,8 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
if(m_lbp) {
// only crc32c lbp mode is supported
drive.enableCRC32CLogicalBlockProtectionReadWrite();
} else {
drive.disableLogicalBlockProtection();
}
mountTape();
......
......@@ -78,6 +78,7 @@ public:
// We will clock the stats for the file itself, and eventually add those
// stats to the session's.
TapeSessionStats localStats;
std::string LBPMode;
castor::utils::Timer localTime;
castor::utils::Timer totalTime(localTime);
......@@ -96,6 +97,7 @@ public:
try {
currentErrorToCount = "Error_tapePositionForRead";
std::unique_ptr<castor::tape::tapeFile::ReadFile> rf(openReadFile(rs,lc));
LBPMode = rf->getLBPMode();
// At that point we already read the header.
localStats.headerVolume += TapeSessionStats::headerVolumePerFile;
......@@ -154,7 +156,8 @@ public:
localStats.totalTime?(1.0*localStats.dataVolume+1.0*localStats.headerVolume)
/1000/1000/localStats.totalTime:0)
.add("payloadTransferSpeedMBps",
localStats.totalTime?1.0*localStats.dataVolume/1000/1000/localStats.totalTime:0);
localStats.totalTime?1.0*localStats.dataVolume/1000/1000/localStats.totalTime:0)
.add("LBPMode", LBPMode);
lc.log(LOG_INFO, "File successfully read from tape");
// Add the local counts to the session's
stats.add(localStats);
......
......@@ -79,11 +79,8 @@ namespace daemon {
// We will clock the stats for the file itself, and eventually add those
// stats to the session's.
castor::utils::Timer localTime;
unsigned long ckSum = Payload::zeroAdler32();
uint32_t memBlockId = 0;
// This out-of-try-catch variables allows us to record the stage of the
......@@ -97,6 +94,7 @@ namespace daemon {
currentErrorToCount = "Error_tapeWriteHeader";
watchdog.notifyBeginNewJob(m_archiveJob->archiveFile.path, m_archiveJob->archiveFile.fileId, m_archiveJob->nameServerTapeFile.tapeFileLocation.fSeq);
std::unique_ptr<castor::tape::tapeFile::WriteFile> output(openWriteFile(session,lc));
m_LBPMode = output->getLBPMode();
m_taskStats.readWriteTime += timer.secs(castor::utils::Timer::resetCounter);
m_taskStats.headerVolume += TapeSessionStats::headerVolumePerFile;
// We are not error sources here until we actually write.
......@@ -323,7 +321,8 @@ namespace daemon {
.add("NSFILEID",m_archiveFile.fileId)
.add("fSeq",m_nameServerTapeFile.tapeFileLocation.fSeq)
.add("lastKnownFilename",m_archiveFile.path)
.add("lastModificationTime",m_archiveFile.lastModificationTime);
.add("lastModificationTime",m_archiveFile.lastModificationTime)
.add("LBPMode", m_LBPMode);
lc.log(level, msg);
......
......@@ -173,6 +173,11 @@ private:
* Stats
*/
TapeSessionStats m_taskStats;
/**
* LBP mode tracking
*/
std::string m_LBPMode;
/**
* The NS archive file information
......
......@@ -442,22 +442,6 @@ void drive::DriveGeneric::enableCRC32CLogicalBlockProtectionReadWrite() {
SCSI::logicBlockProtectionMethod::CRC32CLength,true,true);
}
//------------------------------------------------------------------------------
// enableReedSolomonLogicalBlockProtectionReadOnly
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableReedSolomonLogicalBlockProtectionReadOnly() {
setLogicalBlockProtection(SCSI::logicBlockProtectionMethod::ReedSolomon,
SCSI::logicBlockProtectionMethod::ReedSolomonLength,true,false);
}
//------------------------------------------------------------------------------
// enableReedSolomonLogicalBlockProtectionReadWrite
//------------------------------------------------------------------------------
void drive::DriveGeneric::enableReedSolomonLogicalBlockProtectionReadWrite() {
setLogicalBlockProtection(SCSI::logicBlockProtectionMethod::ReedSolomon,
SCSI::logicBlockProtectionMethod::ReedSolomonLength,true,true);
}
//------------------------------------------------------------------------------
// disableLogicalBlockProtection
//------------------------------------------------------------------------------
......@@ -736,10 +720,16 @@ void drive::DriveGeneric::writeBlock(const void * data, size_t count) {
delete[] dataWithCrc32c;
break;
}
default:
case lbpToUse::crc32cReadOnly:
throw castor::exception::Exception("In DriveGeneric::writeBlock: "
"trying to write a block in CRC-readonly mode");
case lbpToUse::disabled:
castor::exception::Errnum::throwOnMinusOne(
m_sysWrapper.write(m_tapeFD, data, count),
"Failed ST write in DriveGeneric::writeBlock");
default:
throw castor::exception::Exception("In DriveGeneric::writeBlock: "
"unknown LBP mode");
}
}
......@@ -757,15 +747,14 @@ ssize_t drive::DriveGeneric::readBlock(void * data, size_t count) {
uint8_t * dataWithCrc32c =(new (std::nothrow)
uint8_t [count+SCSI::logicBlockProtectionMethod::CRC32CLength]);
if(NULL == dataWithCrc32c) {
throw castor::exception::MemException("Failed to allocate memory "
" for a new MemBlock in DriveGeneric::readBlock!");
throw castor::exception::MemException("In DriveGeneric::readBlock: Failed to allocate memory");
}
ssize_t res = m_sysWrapper.read(m_tapeFD, dataWithCrc32c,
count+SCSI::logicBlockProtectionMethod::CRC32CLength);
if ( -1 == res ) {
delete[] dataWithCrc32c;
castor::exception::Errnum::throwOnMinusOne(res,
"Failed ST read in DriveGeneric::readBlock");
"In DriveGeneric::readBlock: Failed ST read (with checksum)");
}
if ( 0 == res ) {
delete[] dataWithCrc32c;
......@@ -775,8 +764,7 @@ ssize_t drive::DriveGeneric::readBlock(void * data, size_t count) {
SCSI::logicBlockProtectionMethod::CRC32CLength;
if ( 0>= dataLenWithoutCrc32c) {
delete[] dataWithCrc32c;
castor::exception::Errnum::throwOnMinusOne(res,
"Failed ST read in DriveGeneric::readBlock: wrong data block");
throw castor::exception::Exception("In DriveGeneric::readBlock: wrong data block size, checksum cannot fit");
}
if (castor::utils::CRC::verifyCrc32cForMemoryBlockWithCrc32c(
SCSI::logicBlockProtectionMethod::CRC32CSeed,
......@@ -787,23 +775,21 @@ ssize_t drive::DriveGeneric::readBlock(void * data, size_t count) {
return dataLenWithoutCrc32c;
} else {
delete[] dataWithCrc32c;
castor::exception::Errnum::throwOnMinusOne(-1,
"DriveGeneric::readBlock"
"Failed checksum verification for ST read in ");
throw castor::exception::Exception(
"In DriveGeneric::readBlock: Failed checksum verification");
}
break;
}
default:
case lbpToUse::disabled:
{
ssize_t res = m_sysWrapper.read(m_tapeFD, data, count);
castor::exception::Errnum::throwOnMinusOne(res,
"Failed ST read in DriveGeneric::readBlock");
"In DriveGeneric::readBlock: Failed ST read");
return res;
}
default:
throw castor::exception::Exception("In DriveGeneric::readBlock: unknown LBP type");
}
castor::exception::Errnum::throwOnMinusOne(-1,
"Failed in DriveGeneric::readBlock: unknown lpb mode");
return -1; // dummy for compiler
}
/**
......@@ -811,9 +797,9 @@ ssize_t drive::DriveGeneric::readBlock(void * data, size_t count) {
* the exact size of the buffer.
* @param data pointer the the data block
* @param count size of the data block
* @return the actual size of read data
*/
void drive::DriveGeneric::readExactBlock(void * data, size_t count, std::string context) {
switch (m_lbpToUse) {
case lbpToUse::crc32cReadWrite:
case lbpToUse::crc32cReadOnly:
......@@ -852,13 +838,12 @@ void drive::DriveGeneric::readExactBlock(void * data, size_t count, std::string
delete[] dataWithCrc32c;
} else {
delete[] dataWithCrc32c;
castor::exception::Errnum::throwOnMinusOne(-1,
context+"Failed checksum verification for ST read"
castor::exception::Exception(context+"Failed checksum verification for ST read"
" in DriveGeneric::readBlock");
}
break;
}
default:
case lbpToUse::disabled:
{
ssize_t res = m_sysWrapper.read(m_tapeFD, data, count);
// First handle block too big
......@@ -871,6 +856,8 @@ void drive::DriveGeneric::readExactBlock(void * data, size_t count, std::string
if ((size_t) res != count)
throw UnexpectedSize(context);
}
default:
throw castor::exception::Exception("In DriveGeneric::readExactBlock: unknown LBP type");
}
}
......
......@@ -223,39 +223,6 @@ namespace drive {
return m_lbpToUse;
}
/**
* getTapeError: get SENSE buffer from patched version of the driver
* or fall back to other information and report tape statuses.
* Statuses were in CAStor struct sk_info sk_codmsg[] = {
* {"No sense", ETNOSNS},
* {"Recovered error", 0},
* {"Not ready", 0},
* {"Medium error", ETPARIT},
* {"Hardware error", ETHWERR},
* {"Illegal request", ETHWERR},
* {"Unit attention", ETHWERR},
* {"Data protect", 0},
* {"Blank check", ETBLANK},
* {"Vendor unique", 0},
* {"Copy aborted", 0},
* {"Aborted command", 0},
* {"Equal", 0},
* {"Volume overflow", ENOSPC},
* {"Miscompare", 0},
* {"Reserved", 0},
* {"SCSI handshake failure", ETHWERR},
* {"Timeout", ETHWERR},
* {"EOF hit", 0},
* {"EOT hit", ETBLANK},
* {"Length error", ETCOMPA},
* {"BOT hit", ETUNREC},
* {"Wrong tape media", ETCOMPA}
* @return error code and string containing the error description
*/
virtual tapeError getTapeError() {
throw castor::exception::Exception("Not implemented");
}
/**
* Set the buffer write switch in the st driver. This is directly matching a configuration
* parameter in CASTOR, so this function has to be public and usable by a higher level
......@@ -371,18 +338,6 @@ namespace drive {
* Set method CRC32C to be used.
*/
virtual void enableCRC32CLogicalBlockProtectionReadWrite();
/**
* Enable Logical Block Protection on the drive for reading only.
* Set method Reed-Solomon to be used.
*/
virtual void enableReedSolomonLogicalBlockProtectionReadOnly();
/**
* Enable Logical Block Protection on the drive for reading and writing.
* Set method Reed-Solomon to be used.
*/
virtual void enableReedSolomonLogicalBlockProtectionReadWrite();
/**
* Disable Logical Block Protection on the drive.
*/
......
......@@ -183,15 +183,12 @@ namespace drive {
unsigned char densityCode = 0) = 0;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() = 0;
virtual void enableCRC32CLogicalBlockProtectionReadWrite() = 0;
virtual void enableReedSolomonLogicalBlockProtectionReadOnly() = 0;
virtual void enableReedSolomonLogicalBlockProtectionReadWrite() = 0;
virtual void disableLogicalBlockProtection() = 0;
virtual drive::LBPInfo getLBPInfo() = 0;
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite) = 0;
virtual driveStatus getDriveStatus() = 0;
virtual tapeError getTapeError() = 0;
virtual void setSTBufferWrite(bool bufWrite) = 0;
virtual void fastSpaceToEOM(void) = 0;
......
......@@ -113,12 +113,6 @@ void castor::tape::tapeserver::drive::FakeDrive::enableCRC32CLogicalBlockProtect
void castor::tape::tapeserver::drive::FakeDrive::enableCRC32CLogicalBlockProtectionReadWrite() {
m_lbpToUse = lbpToUse::crc32cReadWrite;
}
void castor::tape::tapeserver::drive::FakeDrive::enableReedSolomonLogicalBlockProtectionReadOnly() {
throw castor::exception::Exception("FakeDrive::enableReedSolomonLogicalBlockProtectionReadOnly Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::enableReedSolomonLogicalBlockProtectionReadWrite() {
throw castor::exception::Exception("FakeDrive::enableCReedSolomonLogicalBlockProtectionReadWrite Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::disableLogicalBlockProtection() {
m_lbpToUse = lbpToUse::disabled;
}
......@@ -130,9 +124,6 @@ void castor::tape::tapeserver::drive::FakeDrive::setLogicalBlockProtection(cons
const bool enableLBBforWrite) {
throw castor::exception::Exception("FakeDrive::setLogicalBlockProtection Not implemented");
}
castor::tape::tapeserver::drive::tapeError castor::tape::tapeserver::drive::FakeDrive::getTapeError() {
throw castor::exception::Exception("FakeDrive::getTapeError Not implemented");
}
void castor::tape::tapeserver::drive::FakeDrive::setSTBufferWrite(bool bufWrite) {
throw castor::exception::Exception("FakeDrive::setSTBufferWrite Not implemented");
}
......
......@@ -71,15 +71,12 @@ namespace drive {
unsigned char densityCode = 0) ;
virtual void enableCRC32CLogicalBlockProtectionReadOnly() ;
virtual void enableCRC32CLogicalBlockProtectionReadWrite() ;
virtual void enableReedSolomonLogicalBlockProtectionReadOnly() ;
virtual void enableReedSolomonLogicalBlockProtectionReadWrite() ;
virtual void disableLogicalBlockProtection() ;
virtual drive::LBPInfo getLBPInfo();
virtual void setLogicalBlockProtection(const unsigned char method,
unsigned char methodLength, const bool enableLPBforRead,
const bool enableLBBforWrite);
virtual driveStatus getDriveStatus() ;
virtual tapeError getTapeError() ;
virtual void setSTBufferWrite(bool bufWrite) ;
virtual void fastSpaceToEOM(void) ;
virtual void rewind(void) ;
......
......@@ -78,10 +78,20 @@ namespace castor {
m_detectedLbp = true;
if (m_useLbp) {
m_drive.enableCRC32CLogicalBlockProtectionReadOnly();
} else {
m_drive.disableLogicalBlockProtection();
}
break;
default:
case SCSI::logicBlockProtectionMethod::ReedSolomon:
throw castor::exception::Exception("In ReadSession::ReadSession(): "
"ReedSolomon LBP method not supported");
case SCSI::logicBlockProtectionMethod::DoNotUse:
m_drive.disableLogicalBlockProtection();
m_detectedLbp = false;
break;
default:
throw castor::exception::Exception("In ReadSession::ReadSession(): "
"unknown LBP method");
}
}
......@@ -171,7 +181,8 @@ namespace castor {
ReadFile::ReadFile(ReadSession *rs,
const cta::RetrieveJob &fileToRecall)
: m_currentBlockSize(0), m_session(rs), m_positionCommandCode(fileToRecall.positioningMethod)
: m_currentBlockSize(0), m_session(rs), m_positionCommandCode(fileToRecall.positioningMethod),
m_LBPMode(rs->getLBPMode())
{
if(m_session->isCorrupted()) {
throw SessionCorrupted();
......@@ -363,6 +374,11 @@ namespace castor {
}
return bytes_read;
}
std::string ReadFile::getLBPMode() {
return m_LBPMode;
}
WriteSession::WriteSession(tapeserver::drive::DriveInterface & drive,
const tapeserver::daemon::VolumeInfo& volInfo,
......@@ -402,8 +418,16 @@ namespace castor {
throw ex;
}
break;
default:
case SCSI::logicBlockProtectionMethod::ReedSolomon:
throw castor::exception::Exception("In WriteSession::WriteSession(): "
"ReedSolomon LBP method not supported");
case SCSI::logicBlockProtectionMethod::DoNotUse:
m_drive.disableLogicalBlockProtection();
m_detectedLbp = false;
break;
default:
throw castor::exception::Exception("In WriteSession::WriteSession(): "
"unknown LBP method");
}
}
......@@ -453,6 +477,16 @@ namespace castor {
setHostName();
}
std::string WriteSession::getLBPMode() {
if (m_useLbp && m_detectedLbp)
return "LBP_On";
else if (!m_useLbp && m_detectedLbp)
return "LBP_Off_but_present";
else if (!m_detectedLbp)
return "LBP_Off";
throw castor::exception::Exception("In WriteSession::getLBPMode(): unexpected state");
}
void WriteSession::setHostName() {
char hostname_cstr[max_unix_hostname_length];
castor::exception::Errnum::throwOnMinusOne(gethostname(hostname_cstr, max_unix_hostname_length), "Failed gethostname() in WriteFile::setHostName");
......@@ -524,6 +558,7 @@ namespace castor {
m_session->m_drive.writeBlock(&uhl1, sizeof(uhl1));
m_session->m_drive.writeImmediateFileMarks(1);
m_open=true;
m_LBPMode = m_session->getLBPMode();
}
uint32_t WriteFile::getPosition() {
......@@ -583,6 +618,11 @@ namespace castor {
m_session->release();
}
std::string WriteFile::getLBPMode() {
return m_LBPMode;
}
} //end of namespace tapeFile
} //end of namespace tape
......
......@@ -258,6 +258,16 @@ namespace castor {
return m_currentFilePart;
}
std::string getLBPMode() {
if (m_useLbp && m_detectedLbp)
return "LBP_On";
else if (!m_useLbp && m_detectedLbp)
return "LBP_Off_but_present";
else if (!m_detectedLbp)
return "LBP_Off";
throw castor::exception::Exception("In ReadSession::getLBPMode(): unexpected state");
}
private:
/**
......@@ -323,6 +333,12 @@ namespace castor {
* @return The amount of data actually copied. Zero at end of file.
*/
size_t read(void *data, const size_t size) ;
/**
* Returns the LBP access mode.
* @return The LBP mode.
*/
std::string getLBPMode();
private:
void positionByFseq(const cta::RetrieveJob &fileToRecall) ;
......@@ -359,6 +375,12 @@ namespace castor {
* What kind of command we use to position ourself on the tape (fseq or blockid)
*/
cta::PositioningMethod m_positionCommandCode;
/**
* Description of the LBP mode with which the files is read.
*/
std::string m_LBPMode;
};
/**
......@@ -441,6 +463,7 @@ namespace castor {
void release() throw() {
if(!m_locked) {
m_corrupted = true;
throw SessionCorrupted();
}
m_locked = false;
}
......@@ -480,6 +503,11 @@ namespace castor {
}
m_lastWrittenFSeq = writtenFSeq;
}
/**
* Gets the LBP mode for logs
*/
std::string getLBPMode();
private:
/**
......@@ -575,6 +603,12 @@ namespace castor {
* Destructor of the WriteFile object. Releases the WriteSession
*/
~WriteFile() throw();
/**
* Returns the LBP access mode.
* @return The LBP mode.
*/
std::string getLBPMode();
private:
......@@ -614,6 +648,11 @@ namespace castor {
* This value is retried at open time.
*/
u_int32_t m_blockId;
/**
* Description of the LBP mode with which the files is read.
*/
std::string m_LBPMode;
};
}
} //end of namespace tape
......
......@@ -130,6 +130,8 @@ namespace tape {
};
class VOL1withCrc : public VOL1 {
public:
VOL1withCrc(): VOL1() { m_crc = 0; }
protected:
uint32_t m_crc; // 32bit crc addition for VOL1
};
......
......@@ -74,6 +74,55 @@ namespace unitTests {
vol1Label.backdoorSetLBPMethodString("XY");
ASSERT_THROW(vol1Label.getLBPMethod(), castor::exception::Exception);
}
class testVOL1withCRC: public castor::tape::tapeFile::VOL1withCrc {
public:
void backdoorSetLBPMethodString(const std::string & LBPString) {
::strncpy(m_LBPMethod, LBPString.c_str(), sizeof(m_LBPMethod));
}
};
TEST(castor_tape_AULFile, VOL1WithCRC) {
typedef castor::tape::SCSI::logicBlockProtectionMethod LBPM;
testVOL1withCRC vol1LabelWithCRC;
/**
* Make sure this struct is a POD (plain old data without virtual table)
* (and has the right size).
*/
ASSERT_EQ(80U + 4U, sizeof (vol1LabelWithCRC));
/* test that verify throws exceptions */
EXPECT_ANY_THROW({
vol1LabelWithCRC.verify();
});
vol1LabelWithCRC.fill("test", LBPM::DoNotUse);
ASSERT_NO_THROW({
vol1LabelWithCRC.verify();
});
ASSERT_EQ("test ", vol1LabelWithCRC.getVSN());
/* Validate that parser understands correctly values for LBP */
uint8_t *buf =(uint8_t *) &vol1LabelWithCRC;
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'0');
vol1LabelWithCRC.backdoorSetLBPMethodString(" ");
ASSERT_NO_THROW(vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ((int)LBPM::DoNotUse, (int)vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ(buf[77],' '); ASSERT_EQ(buf[78],' ');
vol1LabelWithCRC.backdoorSetLBPMethodString("01");
ASSERT_NO_THROW(vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ((int)LBPM::ReedSolomon, (int)vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'1');
vol1LabelWithCRC.backdoorSetLBPMethodString("00");
ASSERT_NO_THROW(vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ((int)LBPM::DoNotUse, (int)vol1LabelWithCRC.getLBPMethod());
vol1LabelWithCRC.backdoorSetLBPMethodString("02");
ASSERT_NO_THROW(vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ((int)LBPM::CRC32C, (int)vol1LabelWithCRC.getLBPMethod());
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'2');
vol1LabelWithCRC.backdoorSetLBPMethodString("03");
ASSERT_THROW(vol1LabelWithCRC.getLBPMethod(), castor::exception::Exception);
vol1LabelWithCRC.backdoorSetLBPMethodString("XY");
ASSERT_THROW(vol1LabelWithCRC.getLBPMethod(), castor::exception::Exception);
ASSERT_EQ(0U, *((uint32_t *) &buf[80]));
}
TEST(castor_tape_AULFile, HDR1) {
castor::tape::tapeFile::HDR1 hdr1Label;
......
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