Commit 725bb54a authored by Julien Leduc's avatar Julien Leduc
Browse files

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

00080-CASTOR-5279-Logical-Block-Protection-support-in-the-.patch 36acfd9a5b7a2818732586f70c85a29b7819ca15
parent 39d19881
......@@ -29,6 +29,7 @@
// constructor
//------------------------------------------------------------------------------
castor::legacymsg::TapeLabelRqstMsgBody::TapeLabelRqstMsgBody() throw():
lbp(0),
force(0),
uid(0),
gid(0) {
......
......@@ -33,6 +33,7 @@ namespace legacymsg {
* The body of a TPLABEL message.
*/
struct TapeLabelRqstMsgBody {
uint16_t lbp; // set to 1 if lbp==true, 0 otherwise
uint16_t force; // set to 1 if force==true, 0 otherwise
uint32_t uid;
uint32_t gid;
......
......@@ -303,6 +303,7 @@ size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
// Calculate the length of the message body
const uint32_t bodyLen =
sizeof(src.lbp) + // lbp
sizeof(src.force) + // force
sizeof(src.uid) + // uid
sizeof(src.gid) + // gid
......@@ -342,6 +343,7 @@ size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
// Marshal message body
try {
io::marshalUint16(src.lbp, p);
io::marshalUint16(src.force, p);
io::marshalUint32(src.uid, p);
io::marshalUint32(src.gid, p);
......@@ -421,6 +423,7 @@ void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeConfigR
//-----------------------------------------------------------------------------
void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeLabelRqstMsgBody &dst) {
try {
io::unmarshalUint16(src, srcLen, dst.lbp);
io::unmarshalUint16(src, srcLen, dst.force);
io::unmarshalUint32(src, srcLen, dst.uid);
io::unmarshalUint32(src, srcLen, dst.gid);
......
......@@ -137,11 +137,12 @@ TEST_F(castor_legacymsg_TapeMarshalTest, marshalTapeStatRequestMsgBody) {
TEST_F(castor_legacymsg_TapeMarshalTest, marshalTapeLabelRqstMsgBody) {
using namespace castor::legacymsg;
char buf[45]; // Expect message (header + body) to occupy exactly 27 bytes
char buf[47]; // Expect message (header + body) to occupy exactly 45 bytes
TapeLabelRqstMsgBody srcMsgBody;
// Marshal entire message (header + body)
{
srcMsgBody.lbp = 0xABCD;
srcMsgBody.force = 0;
srcMsgBody.uid = 3;
srcMsgBody.gid = 4;
......@@ -153,7 +154,7 @@ TEST_F(castor_legacymsg_TapeMarshalTest, marshalTapeLabelRqstMsgBody) {
size_t totalLen = 0; // Total length of message (header + body)
ASSERT_NO_THROW(totalLen = marshal(buf, bufLen, srcMsgBody));
ASSERT_EQ((uint32_t)45, totalLen);
ASSERT_EQ((uint32_t)47, totalLen);
}
// Unmarshall message header
......@@ -167,7 +168,7 @@ TEST_F(castor_legacymsg_TapeMarshalTest, marshalTapeLabelRqstMsgBody) {
ASSERT_EQ((uint32_t)TPMAGIC, dstHeader.magic);
ASSERT_EQ((uint32_t)TPLABEL, dstHeader.reqType);
ASSERT_EQ((uint32_t)45, dstHeader.lenOrStatus);
ASSERT_EQ((uint32_t)47, dstHeader.lenOrStatus);
}
// Unmarshall message body
......@@ -175,11 +176,12 @@ TEST_F(castor_legacymsg_TapeMarshalTest, marshalTapeLabelRqstMsgBody) {
TapeLabelRqstMsgBody dstMsgBody;
const char *bufPtr = buf + 12; // Point at beginning of message body
size_t bufLen = 33; // Length of the message body
size_t bufLen = 35; // Length of the message body
ASSERT_NO_THROW(unmarshal(bufPtr, bufLen, dstMsgBody));
ASSERT_EQ(buf + 45, bufPtr);
ASSERT_EQ(buf + 47, bufPtr);
ASSERT_EQ((size_t)0, bufLen);
ASSERT_EQ((uint16_t)0xABCD, dstMsgBody.lbp);
ASSERT_EQ((uint16_t)0, dstMsgBody.force);
ASSERT_EQ((uint32_t)3, dstMsgBody.uid);
ASSERT_EQ((uint32_t)4, dstMsgBody.gid);
......
......@@ -28,8 +28,9 @@ message ForkLabel {
required string libraryslot = 4;
// Description of the label job
required bool force = 5;
required uint32 uid = 6;
required uint32 gid = 7;
required string vid = 8;
required bool lbp = 5;
required bool force = 6;
required uint32 uid = 7;
required uint32 gid = 8;
required string vid = 9;
}
......@@ -39,6 +39,7 @@ set(CTATAPESERVERDAEMON_LIBRARY_SRCS
CatalogueConfig.cpp
CleanerSession.cpp
DataTransferConfig.cpp
LabelSessionConfig.cpp
DiskReadThreadPool.cpp
DiskReadTask.cpp
DiskWriteTask.cpp
......
......@@ -195,7 +195,7 @@ TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessio
{
// Label the tape
castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"],
"V12345");
"V12345", false);
mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
// And write to it
castor::tape::tapeserver::daemon::VolumeInfo volInfo;
......@@ -357,7 +357,7 @@ TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessio
{
// Label the tape
castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"],
"V12345");
"V12345", false);
mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
// And write to it
castor::tape::tapeserver::daemon::VolumeInfo volInfo;
......@@ -511,7 +511,7 @@ TEST_F(castor_tape_tapeserver_daemon_DataTransferSessionTest, DataTransferSessio
{
// Label the tape
castor::tape::tapeFile::LabelSession ls(*mockSys.fake.m_pathToDrive["/dev/nst0"],
"V12345");
"V12345", false);
mockSys.fake.m_pathToDrive["/dev/nst0"]->rewind();
// And write to it
castor::tape::tapeserver::daemon::VolumeInfo volInfo;
......
......@@ -28,6 +28,7 @@
#include "castor/log/LogContext.hpp"
#include "castor/System.hpp"
#include "castor/tape/tapeserver/daemon/LabelSession.hpp"
#include "castor/tape/tapeserver/daemon/LabelSessionConfig.hpp"
#include "castor/tape/tapeserver/drive/DriveInterface.hpp"
#include "castor/tape/tapeserver/file/File.hpp"
#include "castor/tape/tapeserver/file/Structures.hpp"
......@@ -46,7 +47,9 @@ castor::tape::tapeserver::daemon::LabelSession::LabelSession(
castor::log::Logger &log,
System::virtualWrapper &sysWrapper,
const DriveConfig &driveConfig,
const bool force):
const bool force,
const bool lbp,
const LabelSessionConfig &labelSessionConfig):
m_capUtils(capUtils),
m_tapeserver(tapeserver),
m_mc(mc),
......@@ -54,7 +57,9 @@ castor::tape::tapeserver::daemon::LabelSession::LabelSession(
m_log(log),
m_sysWrapper(sysWrapper),
m_driveConfig(driveConfig),
m_force(force) {
m_labelSessionConfig (labelSessionConfig),
m_force(force),
m_lbp(lbp){
}
//------------------------------------------------------------------------------
......@@ -83,6 +88,7 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
params.push_back(log::Param("message", errorMessage));
m_log(LOG_ERR, "Label session failed", params);
......@@ -96,15 +102,36 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
// exceptionThrowingExecute
//------------------------------------------------------------------------------
castor::tape::tapeserver::daemon::Session::EndOfSessionAction
castor::tape::tapeserver::daemon::LabelSession::exceptionThrowingExecute() {
castor::tape::tapeserver::daemon::LabelSession::exceptionThrowingExecute() {
if (!m_labelSessionConfig.useLbp && m_lbp) {
const std::string message = "Tapeserver configuration does not allow label "
"a tape with logical block protection.";
notifyTapeserverOfUserError(message);
return MARK_DRIVE_AS_UP;
}
if (!m_lbp && m_labelSessionConfig.useLbp) {
std::list<log::Param> params;
params.push_back(log::Param("uid", m_request.uid));
params.push_back(log::Param("gid", m_request.gid));
params.push_back(log::Param("TPVID", m_request.vid));
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("dgn", m_request.dgn));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
m_log(LOG_WARNING, "Label session configured to use LBP but lbp parameter "
"is not set", params);
}
setProcessCapabilities("cap_sys_rawio+ep");
mountTape();
std::unique_ptr<drive::DriveInterface> drivePtr = createDrive();
drive::DriveInterface &drive = *drivePtr.get();
if(m_lbp) {
// only crc32c lbp mode is supported
drive.enableCRC32CLogicalBlockProtectionReadWrite();
}
mountTape();
waitUntilTapeLoaded(drive, 60); // 60 = 60 seconds
if(drive.isWriteProtected()) {
......@@ -122,7 +149,11 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
// Else the labeling can go ahead
} else {
writeLabelToTape(drive);
if (m_lbp) {
writeLabelWithLbpToTape(drive);
} else {
writeLabelToTape(drive);
}
}
}
unloadTape(m_request.vid, drive);
......@@ -143,6 +174,7 @@ void castor::tape::tapeserver::daemon::LabelSession::setProcessCapabilities(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
m_capUtils.setProcText(capabilities);
params.push_back(log::Param("capabilities", m_capUtils.getProcText()));
......@@ -183,6 +215,7 @@ void castor::tape::tapeserver::daemon::LabelSession::mountTape() {
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
params.push_back(log::Param("librarySlot", librarySlot.str()));
m_log(LOG_INFO, "Label session mounting tape", params);
......@@ -207,6 +240,7 @@ void castor::tape::tapeserver::daemon::LabelSession::waitUntilTapeLoaded(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
try {
drive.waitUntilReady(timeoutSecond);
......@@ -231,6 +265,7 @@ void castor::tape::tapeserver::daemon::LabelSession::rewindDrive(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
m_log(LOG_INFO, "Label session rewinding tape", params);
drive.rewind();
......@@ -249,6 +284,7 @@ void castor::tape::tapeserver::daemon::LabelSession::
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
params.push_back(log::Param("message", message));
m_log(LOG_ERR, "Label session encountered user error", params);
......@@ -267,12 +303,38 @@ void castor::tape::tapeserver::daemon::LabelSession::writeLabelToTape(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
if(m_lbp) {
m_log(LOG_WARNING, "LBP mode mismatch. Force labeling without lbp.", params);
}
m_log(LOG_INFO, "Label session is writing label to tape", params);
tapeFile::LabelSession ls(drive, m_request.vid);
tapeFile::LabelSession ls(drive, m_request.vid, false);
m_log(LOG_INFO, "Label session has written label to tape", params);
}
//------------------------------------------------------------------------------
// writeLabelWithLbpToTape
//------------------------------------------------------------------------------
void castor::tape::tapeserver::daemon::LabelSession::writeLabelWithLbpToTape(
drive::DriveInterface &drive) {
std::list<log::Param> params;
params.push_back(log::Param("uid", m_request.uid));
params.push_back(log::Param("gid", m_request.gid));
params.push_back(log::Param("TPVID", m_request.vid));
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("dgn", m_request.dgn));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
if(!m_lbp) {
m_log(LOG_WARNING, "LBP mode mismatch. Force labeling with lbp.", params);
}
m_log(LOG_INFO, "Label session is writing label with LBP to tape", params);
tapeFile::LabelSession ls(drive, m_request.vid, true);
m_log(LOG_INFO, "Label session has written label with LBP to tape", params);
}
//------------------------------------------------------------------------------
// unloadTape
//------------------------------------------------------------------------------
......@@ -285,6 +347,7 @@ void castor::tape::tapeserver::daemon::LabelSession::unloadTape(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
// We implement the same policy as with the tape sessions:
// if the librarySlot parameter is "manual", do nothing.
......@@ -320,6 +383,7 @@ void castor::tape::tapeserver::daemon::LabelSession::dismountTape(
params.push_back(log::Param("unitName", m_request.drive));
params.push_back(log::Param("logicalLibrary", m_request.logicalLibrary));
params.push_back(log::Param("force", boolToStr(m_force)));
params.push_back(log::Param("lbp", boolToStr(m_lbp)));
params.push_back(log::Param("librarySlot", librarySlot.str()));
try {
......
......@@ -35,6 +35,7 @@
#include "castor/tape/tapeserver/drive/DriveInterface.hpp"
#include "castor/tape/tapeserver/SCSI/Device.hpp"
#include "castor/tape/tapeserver/system/Wrapper.hpp"
#include "castor/tape/tapeserver/daemon/LabelSessionConfig.hpp"
#include <memory>
......@@ -63,6 +64,9 @@ public:
* label a tape.
* @param force The flag that, if set to true, allows labeling a non-blank
* tape.
* @param lbp The flag that, if set to true, allows labeling a tape with
* logical block protection. This parameter comes from
* castor-tape-label command line tool.
*/
LabelSession(
server::ProcessCap &capUtils,
......@@ -72,7 +76,9 @@ public:
castor::log::Logger &log,
System::virtualWrapper &sysWrapper,
const DriveConfig &driveConfig,
const bool force);
const bool force,
const bool lbp,
const LabelSessionConfig &labelSessionConfig);
/**
* Execute the session and return the type of action to be performed
......@@ -120,10 +126,21 @@ private:
*/
const DriveConfig m_driveConfig;
/**
* The configuration parameters from castor.conf specific for of the tape drive to be used to label a tape.
*/
const LabelSessionConfig m_labelSessionConfig;
/**
* The flag that, if set to true, allows labeling a non-blank tape
*/
const bool m_force;
/**
* The flag that, if set to true, allows labeling a tape with logical
* block protection
*/
const bool m_lbp;
/**
* Execute the session and return the type of action to be performed
......@@ -200,6 +217,15 @@ private:
*/
void writeLabelToTape(drive::DriveInterface &drive);
/**
* Writes the label file with logical block protection to the tape.
*
* This method assumes the tape has been rewound.
*
* @param drive The tape drive.
*/
void writeLabelWithLbpToTape(drive::DriveInterface &drive);
/**
* Unloads the specified tape from the specified tape drive.
*
......
......@@ -864,7 +864,9 @@ castor::tape::tapeserver::daemon::Session::EndOfSessionAction
m_log,
sWrapper,
driveConfig,
rqst.force());
rqst.force(),
rqst.lbp(),
m_config.labelSession);
return labelsession.execute();
} catch(castor::exception::Exception &ex) {
throw ex;
......@@ -886,6 +888,7 @@ castor::legacymsg::TapeLabelRqstMsgBody
castor::tape::tapeserver::daemon::ProcessForker::getLabelJob(
const messages::ForkLabel &msg) {
castor::legacymsg::TapeLabelRqstMsgBody job;
job.lbp = msg.lbp() ? 1 : 0;
job.force = msg.force() ? 1 : 0;
job.uid = msg.uid();
job.gid = msg.gid();
......
......@@ -180,6 +180,7 @@ private:
*/
template <typename T> void fillMsgWithLabelJob(T &msg,
const legacymsg::TapeLabelRqstMsgBody &labelJob) {
msg.set_lbp(labelJob.lbp);
msg.set_force(labelJob.force);
msg.set_uid(labelJob.uid);
msg.set_gid(labelJob.gid);
......
......@@ -65,6 +65,7 @@ castor::tape::tapeserver::daemon::TapeDaemonConfig
TAPESERVER_INTERNAL_PORT, log);
config.dataTransfer = DataTransferConfig::createFromCastorConf(log);
config.labelSession = LabelSessionConfig::createFromCastorConf(log);
return config;
}
......
......@@ -27,6 +27,7 @@
#include "castor/log/Logger.hpp"
#include "castor/tape/tapeserver/daemon/CatalogueConfig.hpp"
#include "castor/tape/tapeserver/daemon/DataTransferConfig.hpp"
#include "castor/tape/tapeserver/daemon/LabelSessionConfig.hpp"
#include <stdint.h>
#include <string>
......@@ -91,6 +92,11 @@ struct TapeDaemonConfig {
*/
DataTransferConfig dataTransfer;
/**
* The configuration parameters required by a label session.
*/
LabelSessionConfig labelSession;
/**
* Constructor.
*
......
......@@ -163,8 +163,13 @@ namespace castor {
* labeled is already mounted and rewound.
* @param drive: drive object to which we bind the session
* @param vid: volume name of the tape we would like to read from
* @param lbp The boolean variable for logical block protection mode.
* If it is true than the label will be written with LBP or
* without otherwise.
*
*/
LabelSession(tapeserver::drive::DriveInterface & drive, const std::string &vid);
LabelSession(tapeserver::drive::DriveInterface & drive,
const std::string &vid, const bool lbp);
};
/**
......
......@@ -67,9 +67,12 @@ namespace unitTests {
fileToMigrate.nameServerTapeFile.tapeFileLocation.fSeq = 1;
volInfo.vid= label;
//Label
castor::tape::tapeFile::LabelSession *ls;
ls = new castor::tape::tapeFile::LabelSession(d, label);
delete ls;
castor::tape::tapeFile::LabelSession *lsWithoutLbp;
lsWithoutLbp = new castor::tape::tapeFile::LabelSession(d, label, false);
delete lsWithoutLbp;
castor::tape::tapeFile::LabelSession *lsWithout;
lsWithout = new castor::tape::tapeFile::LabelSession(d, label, true);
delete lsWithout;
}
virtual void TearDown() {
......
......@@ -38,7 +38,7 @@ void tapeFile::VOL1::fill(std::string VSN,
setString(m_ownerID, "CASTOR");
std::stringstream hexLBP;
hexLBP << std::setfill('0') << std::setw(2) << std::hex
<< std::noshowbase << LBPMethod;
<< std::noshowbase << static_cast<int>(LBPMethod);
setString(m_LBPMethod, hexLBP.str());
}
......
......@@ -68,7 +68,7 @@ namespace tape {
char m_implID[13]; // The Implementation Identifier - spaces.
char m_ownerID[14]; // CASTOR or stagesuperuser name padded with spaces.
char m_reserved2[26]; // Reserved
char m_LBPMethod[2]; // Logic block protection checksum type.
char m_LBPMethod[2]; // Logic block protection checksum type.
// This field is a CASTOR variation from the ECMA 013/ISO1001
// standard. It contains 2 spaces or '00'. Otherwise, contains
// the ASCII representation of the hexadecimal value of the
......
......@@ -52,18 +52,23 @@ namespace unitTests {
});
ASSERT_EQ("test ", vol1Label.getVSN());
/* Validate that parser understands correctly values for LBP */
uint8_t *buf =(uint8_t *) &vol1Label;
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'0');
vol1Label.backdoorSetLBPMethodString(" ");
ASSERT_NO_THROW(vol1Label.getLBPMethod());
ASSERT_EQ((int)LBPM::DoNotUse, (int)vol1Label.getLBPMethod());
ASSERT_EQ(buf[77],' '); ASSERT_EQ(buf[78],' ');
vol1Label.backdoorSetLBPMethodString("01");
ASSERT_NO_THROW(vol1Label.getLBPMethod());
ASSERT_EQ((int)LBPM::ReedSolomon, (int)vol1Label.getLBPMethod());
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'1');
vol1Label.backdoorSetLBPMethodString("00");
ASSERT_NO_THROW(vol1Label.getLBPMethod());
ASSERT_EQ((int)LBPM::DoNotUse, (int)vol1Label.getLBPMethod());
vol1Label.backdoorSetLBPMethodString("02");
ASSERT_NO_THROW(vol1Label.getLBPMethod());
ASSERT_EQ((int)LBPM::CRC32C, (int)vol1Label.getLBPMethod());
ASSERT_EQ(buf[77],'0'); ASSERT_EQ(buf[78],'2');
vol1Label.backdoorSetLBPMethodString("03");
ASSERT_THROW(vol1Label.getLBPMethod(), castor::exception::Exception);
vol1Label.backdoorSetLBPMethodString("XY");
......
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