New upstream version 8.1.0

This commit is contained in:
geos_one
2025-08-10 01:34:16 +02:00
commit c891bb7105
4398 changed files with 838833 additions and 0 deletions

562
fsck/source/app/App.cpp Normal file
View File

@@ -0,0 +1,562 @@
#include <common/components/RegistrationDatagramListener.h>
#include <program/Program.h>
#include <toolkit/FsckTkEx.h>
#include <csignal>
#include <syslog.h>
#define APP_WORKERS_DIRECT_NUM 1
#define APP_SYSLOG_IDENTIFIER "beegfs-fsck"
App::App(int argc, char** argv)
{
this->argc = argc;
this->argv = argv;
this->appResult = APPCODE_NO_ERROR;
this->cfg = NULL;
this->netFilter = NULL;
this->tcpOnlyFilter = NULL;
this->log = NULL;
this->mgmtNodes = NULL;
this->metaNodes = NULL;
this->storageNodes = NULL;
this->internodeSyncer = NULL;
this->targetMapper = NULL;
this->targetStateStore = NULL;
this->buddyGroupMapper = NULL;
this->metaBuddyGroupMapper = NULL;
this->workQueue = NULL;
this->ackStore = NULL;
this->netMessageFactory = NULL;
this->dgramListener = NULL;
this->modificationEventHandler = NULL;
this->runMode = NULL;
}
App::~App()
{
// Note: Logging of the common lib classes is not working here, because this is called
// from class Program (so the thread-specific app-pointer isn't set in this context).
workersDelete();
SAFE_DELETE(this->dgramListener);
SAFE_DELETE(this->netMessageFactory);
SAFE_DELETE(this->ackStore);
SAFE_DELETE(this->workQueue);
SAFE_DELETE(this->storageNodes);
SAFE_DELETE(this->metaNodes);
SAFE_DELETE(this->mgmtNodes);
this->localNode.reset();
SAFE_DELETE(this->buddyGroupMapper);
SAFE_DELETE(this->metaBuddyGroupMapper);
SAFE_DELETE(this->targetStateStore);
SAFE_DELETE(this->targetMapper);
SAFE_DELETE(this->internodeSyncer);
SAFE_DELETE(this->log);
SAFE_DELETE(this->tcpOnlyFilter);
SAFE_DELETE(this->netFilter);
SAFE_DELETE(this->cfg);
SAFE_DELETE(this->runMode);
Logger::destroyLogger();
closelog();
}
void App::run()
{
try
{
openlog(APP_SYSLOG_IDENTIFIER, LOG_NDELAY | LOG_PID | LOG_CONS, LOG_DAEMON);
this->cfg = new Config(argc, argv);
runNormal();
}
catch (InvalidConfigException& e)
{
std::cerr << std::endl;
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << std::endl;
std::cerr << std::endl;
if(this->log)
log->logErr(e.what() );
this->appResult = APPCODE_INVALID_CONFIG;
return;
}
catch (std::exception& e)
{
std::cerr << std::endl;
std::cerr << "Unrecoverable error: " << e.what() << std::endl;
std::cerr << std::endl;
if(this->log)
log->logErr(e.what() );
appResult = APPCODE_RUNTIME_ERROR;
return;
}
}
void App::runNormal()
{
bool componentsStarted = false;
auto runModeEnum = Program::getApp()->getConfig()->determineRunMode();
if (runModeEnum == RunMode_CHECKFS || runModeEnum == RunMode_ENABLEQUOTA)
{
// check if running as root
if(geteuid())
{
std::cerr << std::endl
<< "Running beegfs-fsck requires root privileges."
<< std::endl << std::endl << std::endl;
ModeHelp().execute();
appResult = APPCODE_INITIALIZATION_ERROR;
return;
}
if (runModeEnum == RunMode_CHECKFS)
runMode = new ModeCheckFS();
else if (runModeEnum == RunMode_ENABLEQUOTA)
runMode = new ModeEnableQuota();
}
else if (runModeEnum == RunMode_HELP)
{
appResult = ModeHelp().execute();
return;
}
else
{
ModeHelp().execute();
appResult = APPCODE_INVALID_CONFIG;
return;
}
initDataObjects(argc, argv);
// wait for mgmtd
if ( !cfg->getSysMgmtdHost().length() )
throw InvalidConfigException("Management host undefined");
bool mgmtWaitRes = waitForMgmtNode();
if(!mgmtWaitRes)
{ // typically user just pressed ctrl+c in this case
log->logErr("Waiting for beegfs-mgmtd canceled");
appResult = APPCODE_RUNTIME_ERROR;
return;
}
// init components
try
{
initComponents();
}
catch (ComponentInitException& e)
{
FsckTkEx::fsckOutput(e.what(), OutputOptions_DOUBLELINEBREAK | OutputOptions_STDERR);
FsckTkEx::fsckOutput("A hard error occurred. BeeGFS Fsck will abort.",
OutputOptions_LINEBREAK | OutputOptions_STDERR);
appResult = APPCODE_INITIALIZATION_ERROR;
return;
}
// log system and configuration info
logInfos();
// start component threads
startComponents();
componentsStarted = true;
try
{
appResult = runMode->execute();
}
catch (InvalidConfigException& e)
{
ModeHelp modeHelp;
modeHelp.execute();
appResult = APPCODE_INVALID_CONFIG;
}
catch (std::exception &e)
{
FsckTkEx::fsckOutput("Unrecoverable error. BeeGFS Fsck will abort.",
OutputOptions_LINEBREAK | OutputOptions_ADDLINEBREAKBEFORE | OutputOptions_STDERR);
FsckTkEx::fsckOutput(e.what(), OutputOptions_LINEBREAK | OutputOptions_STDERR);
}
// self-termination
if(componentsStarted)
{
stopComponents();
joinComponents();
}
}
void App::initDataObjects(int argc, char** argv)
{
this->netFilter = new NetFilter(cfg->getConnNetFilterFile() );
this->tcpOnlyFilter = new NetFilter(cfg->getConnTcpOnlyFilterFile() );
Logger::createLogger(cfg->getLogLevel(), cfg->getLogType(), cfg->getLogNoDate(),
cfg->getLogStdFile(), cfg->getLogNumLines(), cfg->getLogNumRotatedFiles());
this->log = new LogContext("App");
std::string interfacesFilename = this->cfg->getConnInterfacesFile();
if ( interfacesFilename.length() )
Config::loadStringListFile(interfacesFilename.c_str(), this->allowedInterfaces);
this->targetMapper = new TargetMapper();
this->targetStateStore = new TargetStateStore(NODETYPE_Storage);
this->buddyGroupMapper = new MirrorBuddyGroupMapper(targetMapper);
this->metaBuddyGroupMapper = new MirrorBuddyGroupMapper();
this->mgmtNodes = new NodeStoreServers(NODETYPE_Mgmt, false);
this->metaNodes = new NodeStoreServers(NODETYPE_Meta, false);
this->storageNodes = new NodeStoreServers(NODETYPE_Storage, false);
this->workQueue = new MultiWorkQueue();
this->ackStore = new AcknowledgmentStore();
initLocalNodeInfo();
registerSignalHandler();
this->netMessageFactory = new NetMessageFactory();
}
void App::findAllowedRDMAInterfaces(NicAddressList& outList) const
{
Config* cfg = this->getConfig();
if(cfg->getConnUseRDMA() && RDMASocket::rdmaDevicesExist() )
{
bool foundRdmaInterfaces = NetworkInterfaceCard::checkAndAddRdmaCapability(outList);
if (foundRdmaInterfaces)
outList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces}); // re-sort the niclist
}
}
void App::findAllowedInterfaces(NicAddressList& outList) const
{
// discover local NICs and filter them
NetworkInterfaceCard::findAllInterfaces(allowedInterfaces, outList);
outList.sort(NetworkInterfaceCard::NicAddrComp{&allowedInterfaces});
}
void App::initLocalNodeInfo()
{
findAllowedInterfaces(localNicList);
findAllowedRDMAInterfaces(localNicList);
if ( this->localNicList.empty() )
throw InvalidConfigException("Couldn't find any usable NIC");
initRoutingTable();
updateRoutingTable();
std::string nodeID = System::getHostname();
this->localNode = std::make_shared<LocalNode>(NODETYPE_Client, nodeID, NumNodeID(), 0, 0,
this->localNicList);
}
void App::initComponents()
{
this->log->log(Log_DEBUG, "Initializing components...");
// Note: We choose a random udp port here to avoid conflicts with the client
unsigned short udpListenPort = 0;
this->dgramListener = new DatagramListener(netFilter, localNicList, ackStore, udpListenPort,
this->cfg->getConnRestrictOutboundInterfaces());
// update the local node info with udp port
this->localNode->updateInterfaces(dgramListener->getUDPPort(), 0, this->localNicList);
this->internodeSyncer = new InternodeSyncer();
workersInit();
this->log->log(Log_DEBUG, "Components initialized.");
}
void App::startComponents()
{
log->log(Log_SPAM, "Starting up components...");
// make sure child threads don't receive SIGINT/SIGTERM (blocked signals are inherited)
PThread::blockInterruptSignals();
dgramListener->start();
internodeSyncer->start();
internodeSyncer->waitForServers();
workersStart();
PThread::unblockInterruptSignals(); // main app thread may receive SIGINT/SIGTERM
log->log(Log_DEBUG, "Components running.");
}
void App::stopComponents()
{
// note: this method may not wait for termination of the components, because that could
// lead to a deadlock (when calling from signal handler)
workersStop();
if(this->internodeSyncer)
this->internodeSyncer->selfTerminate();
if ( dgramListener )
{
dgramListener->selfTerminate();
dgramListener->sendDummyToSelfUDP();
}
this->selfTerminate();
}
void App::joinComponents()
{
log->log(4, "Joining component threads...");
this->internodeSyncer->join();
/* (note: we need one thread for which we do an untimed join, so this should be a quite reliably
terminating thread) */
this->dgramListener->join();
workersJoin();
}
void App::workersInit()
{
unsigned numWorkers = cfg->getTuneNumWorkers();
for(unsigned i=0; i < numWorkers; i++)
{
Worker* worker = new Worker(
std::string("Worker") + StringTk::intToStr(i+1), workQueue, QueueWorkType_INDIRECT);
workerList.push_back(worker);
}
for(unsigned i=0; i < APP_WORKERS_DIRECT_NUM; i++)
{
Worker* worker = new Worker(
std::string("DirectWorker") + StringTk::intToStr(i+1), workQueue, QueueWorkType_DIRECT);
workerList.push_back(worker);
}
}
void App::workersStart()
{
for ( WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++ )
{
(*iter)->start();
}
}
void App::workersStop()
{
// need two loops because we don't know if the worker that handles the work will be the same that
// received the self-terminate-request
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
{
(*iter)->selfTerminate();
}
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
{
workQueue->addDirectWork(new DummyWork() );
}
}
void App::workersDelete()
{
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
{
delete(*iter);
}
workerList.clear();
}
void App::workersJoin()
{
for(WorkerListIter iter = workerList.begin(); iter != workerList.end(); iter++)
{
waitForComponentTermination(*iter);
}
}
void App::logInfos()
{
// print software version (BEEGFS_VERSION)
log->log(Log_NOTICE, std::string("Version: ") + BEEGFS_VERSION);
// print debug version info
LOG_DEBUG_CONTEXT(*log, Log_CRITICAL, "--DEBUG VERSION--");
// print local nodeID
log->log(Log_NOTICE, std::string("LocalNode: ") + localNode->getTypedNodeID() );
// list usable network interfaces
NicAddressList nicList(localNode->getNicList());
logUsableNICs(log, nicList);
// print net filters
if ( netFilter->getNumFilterEntries() )
{
this->log->log(2,
std::string("Net filters: ") + StringTk::uintToStr(netFilter->getNumFilterEntries()));
}
if(tcpOnlyFilter->getNumFilterEntries() )
{
this->log->log(Log_WARNING, std::string("TCP-only filters: ") +
StringTk::uintToStr(tcpOnlyFilter->getNumFilterEntries() ) );
}
}
/**
* Request mgmt heartbeat and wait for the mgmt node to appear in nodestore.
*
* @return true if mgmt heartbeat received, false on error or thread selftermination order
*/
bool App::waitForMgmtNode()
{
const unsigned waitTimeoutMS = 0; // infinite wait
const unsigned nameResolutionRetries = 3;
// choose a random udp port here
unsigned udpListenPort = 0;
unsigned udpMgmtdPort = cfg->getConnMgmtdPort();
std::string mgmtdHost = cfg->getSysMgmtdHost();
RegistrationDatagramListener regDGramLis(this->netFilter, this->localNicList, this->ackStore,
udpListenPort, this->cfg->getConnRestrictOutboundInterfaces());
regDGramLis.start();
log->log(Log_CRITICAL, "Waiting for beegfs-mgmtd@" +
mgmtdHost + ":" + StringTk::uintToStr(udpMgmtdPort) + "...");
bool gotMgmtd = NodesTk::waitForMgmtHeartbeat(
this, &regDGramLis, this->mgmtNodes, mgmtdHost, udpMgmtdPort, waitTimeoutMS,
nameResolutionRetries);
regDGramLis.selfTerminate();
regDGramLis.sendDummyToSelfUDP(); // for faster termination
regDGramLis.join();
return gotMgmtd;
}
void App::updateLocalNicList(NicAddressList& localNicList)
{
std::vector<AbstractNodeStore*> allNodes({ mgmtNodes, metaNodes, storageNodes});
updateLocalNicListAndRoutes(log, localNicList, allNodes);
localNode->updateInterfaces(0, 0, localNicList);
dgramListener->setLocalNicList(localNicList);
}
/*
* Handles expections that lead to the termination of a component.
* Initiates an application shutdown.
*/
void App::handleComponentException(std::exception& e)
{
const char* logContext = "App (component exception handler)";
LogContext log(logContext);
const auto componentName = PThread::getCurrentThreadName();
log.logErr(
"The component [" + componentName + "] encountered an unrecoverable error. " +
std::string("[SysErr: ") + System::getErrString() + "] " +
std::string("Exception message: ") + e.what() );
log.log(2, "Shutting down...");
shallAbort.set(1);
stopComponents();
}
void App::handleNetworkInterfaceFailure(const std::string& devname)
{
LOG(GENERAL, ERR, "Network interface failure.",
("Device", devname));
internodeSyncer->setForceCheckNetwork();
}
void App::registerSignalHandler()
{
signal(SIGINT, App::signalHandler);
signal(SIGTERM, App::signalHandler);
}
void App::signalHandler(int sig)
{
App* app = Program::getApp();
Logger* log = Logger::getLogger();
const char* logContext = "App::signalHandler";
// note: this might deadlock if the signal was thrown while the logger mutex is locked by the
// application thread (depending on whether the default mutex style is recursive). but
// even recursive mutexes are not acceptable in this case.
// we need something like a timed lock for the log mutex. if it succeeds within a
// few seconds, we know that we didn't hold the mutex lock. otherwise we simply skip the
// log message. this will only work if the mutex is non-recusive (which is unknown for
// the default mutex style).
// but it is very unlikely that the application thread holds the log mutex, because it
// joins the component threads and so it doesn't do anything else but sleeping!
switch(sig)
{
case SIGINT:
{
signal(sig, SIG_DFL); // reset the handler to its default
log->log(1, logContext, "Received a SIGINT. Shutting down...");
}
break;
case SIGTERM:
{
signal(sig, SIG_DFL); // reset the handler to its default
log->log(1, logContext, "Received a SIGTERM. Shutting down...");
}
break;
default:
{
signal(sig, SIG_DFL); // reset the handler to its default
log->log(1, logContext, "Received an unknown signal. Shutting down...");
}
break;
}
app->abort();
}
void App::abort()
{
shallAbort.set(1);
stopComponents();
}

223
fsck/source/app/App.h Normal file
View File

@@ -0,0 +1,223 @@
#ifndef APP_H_
#define APP_H_
#include <app/config/Config.h>
#include <common/app/log/LogContext.h>
#include <common/app/log/Logger.h>
#include <common/app/AbstractApp.h>
#include <common/nodes/NodeStore.h>
#include <common/toolkit/AcknowledgmentStore.h>
#include <common/toolkit/NetFilter.h>
#include <common/toolkit/NodesTk.h>
#include <common/Common.h>
#include <common/components/worker/Worker.h>
#include <common/components/worker/DummyWork.h>
#include <common/components/ComponentInitException.h>
#include <common/net/sock/RDMASocket.h>
#include <common/nodes/RootInfo.h>
#include <common/nodes/TargetMapper.h>
#include <common/nodes/LocalNode.h>
#include <components/DatagramListener.h>
#include <components/InternodeSyncer.h>
#include <components/ModificationEventHandler.h>
#include <modes/ModeHelp.h>
#include <modes/ModeCheckFS.h>
#include <modes/ModeEnableQuota.h>
#include <net/message/NetMessageFactory.h>
#ifndef BEEGFS_VERSION
#error BEEGFS_VERSION undefined
#endif
// program return codes
#define APPCODE_NO_ERROR 0
#define APPCODE_INVALID_CONFIG 1
#define APPCODE_INITIALIZATION_ERROR 2
#define APPCODE_COMMUNICATION_ERROR 3
#define APPCODE_RUNTIME_ERROR 4
#define APPCODE_USER_ABORTED 5
typedef std::list<Worker*> WorkerList;
typedef WorkerList::iterator WorkerListIter;
// forward declarations
class LogContext;
class App : public AbstractApp
{
public:
App(int argc, char** argv);
virtual ~App();
virtual void run() override;
void abort();
virtual void handleComponentException(std::exception& e) override;
virtual void handleNetworkInterfaceFailure(const std::string& devname) override;
bool getShallAbort()
{
return (shallAbort.read() != 0);
}
private:
int appResult;
int argc;
char** argv;
AtomicSizeT shallAbort;
Config* cfg;
LogContext* log;
NetFilter* netFilter;
NetFilter* tcpOnlyFilter; // for IPs that allow only plain TCP (no RDMA etc)
std::list<std::string> allowedInterfaces;
std::shared_ptr<Node> localNode;
NodeStore* mgmtNodes;
NodeStore* metaNodes;
NodeStore* storageNodes;
RootInfo metaRoot;
InternodeSyncer* internodeSyncer;
TargetMapper* targetMapper;
TargetStateStore* targetStateStore;
MirrorBuddyGroupMapper* buddyGroupMapper;
MirrorBuddyGroupMapper* metaBuddyGroupMapper;
MultiWorkQueue* workQueue;
AcknowledgmentStore* ackStore;
NetMessageFactory* netMessageFactory;
DatagramListener* dgramListener;
WorkerList workerList;
ModificationEventHandler* modificationEventHandler;
Mode* runMode;
void runNormal();
void workersInit();
void workersStart();
void workersStop();
void workersDelete();
void workersJoin();
void initDataObjects(int argc, char** argv);
void initLocalNodeInfo();
void initComponents();
bool initRunMode();
void startComponents();
void joinComponents();
virtual void stopComponents() override;
void logInfos();
bool waitForMgmtNode();
void registerSignalHandler();
static void signalHandler(int sig);
public:
virtual const ICommonConfig* getCommonConfig() const override
{
return cfg;
}
virtual const AbstractNetMessageFactory* getNetMessageFactory() const override
{
return netMessageFactory;
}
virtual const NetFilter* getNetFilter() const override
{
return netFilter;
}
virtual const NetFilter* getTcpOnlyFilter() const override
{
return tcpOnlyFilter;
}
Config* getConfig() const
{
return cfg;
}
DatagramListener* getDatagramListener() const
{
return dgramListener;
}
int getAppResult() const
{
return appResult;
}
NodeStore* getMgmtNodes() const
{
return mgmtNodes;
}
NodeStore* getMetaNodes()
{
return metaNodes;
}
NodeStore* getStorageNodes() const
{
return storageNodes;
}
Node& getLocalNode() const
{
return *localNode;
}
void updateLocalNicList(NicAddressList& localNicList);
MultiWorkQueue* getWorkQueue()
{
return workQueue;
}
InternodeSyncer* getInternodeSyncer()
{
return internodeSyncer;
}
TargetMapper* getTargetMapper()
{
return targetMapper;
}
TargetStateStore* getTargetStateStore()
{
return targetStateStore;
}
MirrorBuddyGroupMapper* getMirrorBuddyGroupMapper()
{
return buddyGroupMapper;
}
MirrorBuddyGroupMapper* getMetaMirrorBuddyGroupMapper()
{
return metaBuddyGroupMapper;
}
ModificationEventHandler* getModificationEventHandler()
{
return modificationEventHandler;
}
void setModificationEventHandler(ModificationEventHandler* handler)
{
modificationEventHandler = handler;
}
const RootInfo& getMetaRoot() const { return metaRoot; }
RootInfo& getMetaRoot() { return metaRoot; }
void findAllowedInterfaces(NicAddressList& outList) const;
void findAllowedRDMAInterfaces(NicAddressList& outList) const;
};
#endif // APP_H_

View File

@@ -0,0 +1,317 @@
#include <common/toolkit/StringTk.h>
#include "Config.h"
#define IGNORE_CONFIG_CLIENT_VALUE(keyStr) /* to be used in applyConfigMap() */ \
if(testConfigMapKeyMatch(iter, keyStr, addDashes) ) \
; \
else
// Note: Keep in sync with enum RunMode
RunModesElem const __RunModes[] =
{
{ "--checkfs", RunMode_CHECKFS },
{ "--enablequota", RunMode_ENABLEQUOTA },
{ NULL, RunMode_INVALID }
};
Config::Config(int argc, char** argv) :
AbstractConfig(argc, argv)
{
initConfig(argc, argv, false, true);
logType = LogType_LOGFILE;
}
/**
* Determine RunMode from config.
* If a valid RunMode exists in the config, the corresponding config element will be erased.
*/
enum RunMode Config::determineRunMode()
{
/* test for given help argument, e.g. in case the user wants to see mode-specific help with
arguments "--help --<mode>". */
StringMapIter iter = configMap.find(RUNMODE_HELP_KEY_STRING);
if(iter != configMap.end() )
{ // user did specify "--help"
/* note: it's important to remove the help arg here, because mode help will call this again
to find out whether user wants to see mode-specific help. */
eraseFromConfigMap(iter);
return RunMode_HELP;
}
// walk all defined modes to check whether we find any of them in the config
for(int i=0; __RunModes[i].modeString != NULL; i++)
{
iter = configMap.find(__RunModes[i].modeString);
if(iter != configMap.end() )
{ // we found a valid mode in the config
eraseFromConfigMap(iter);
return __RunModes[i].runMode;
}
}
// no valid mode found
return RunMode_INVALID;
}
/**
* Sets the default values for each configurable in the configMap.
*
* @param addDashes true to prepend "--" to all config keys.
*/
void Config::loadDefaults(bool addDashes)
{
AbstractConfig::loadDefaults(addDashes);
// re-definitions
configMapRedefine("cfgFile", createDefaultCfgFilename(), addDashes);
// own definitions
configMapRedefine("connInterfacesFile", "", addDashes);
configMapRedefine("tuneNumWorkers", "32", addDashes);
configMapRedefine("tunePreferredNodesFile", "", addDashes);
configMapRedefine("tuneDbFragmentSize", "0", addDashes);
configMapRedefine("tuneDentryCacheSize", "0", addDashes);
configMapRedefine("runDaemonized", "false", addDashes);
configMapRedefine("databasePath", CONFIG_DEFAULT_DBPATH, addDashes);
configMapRedefine("overwriteDbFile", "false", addDashes);
configMapRedefine("testDatabasePath", CONFIG_DEFAULT_TESTDBPATH, addDashes);
configMapRedefine("DatabaseNumMaxConns", "16", addDashes);
configMapRedefine("overrideRootMDS", "", addDashes);
configMapRedefine("logStdFile", CONFIG_DEFAULT_LOGFILE, addDashes);
configMapRedefine("logOutFile", CONFIG_DEFAULT_OUTFILE, addDashes);
configMapRedefine("logNoDate", "false", addDashes);
configMapRedefine("readOnly", "false", addDashes);
configMapRedefine("noFetch", "false", addDashes);
configMapRedefine("automatic", "false", addDashes);
configMapRedefine("runOffline", "false", addDashes);
configMapRedefine("forceRestart", "false", addDashes);
configMapRedefine("quotaEnabled", "false", addDashes);
configMapRedefine("ignoreDBDiskSpace", "false", addDashes);
}
/**
* @param addDashes true to prepend "--" to tested config keys for matching.
*/
void Config::applyConfigMap(bool enableException, bool addDashes)
{
AbstractConfig::applyConfigMap(false, addDashes);
for (StringMapIter iter = configMap.begin(); iter != configMap.end();)
{
bool unknownElement = false;
IGNORE_CONFIG_CLIENT_VALUE("logClientID")
IGNORE_CONFIG_CLIENT_VALUE("logType")
IGNORE_CONFIG_CLIENT_VALUE("connNumCommRetries")
IGNORE_CONFIG_CLIENT_VALUE("connUnmountRetries")
IGNORE_CONFIG_CLIENT_VALUE("connCommRetrySecs")
IGNORE_CONFIG_CLIENT_VALUE("connMaxConcurrentAttempts")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAInterfacesFile")
IGNORE_CONFIG_CLIENT_VALUE("connTCPFallbackEnabled")
IGNORE_CONFIG_CLIENT_VALUE("connMessagingTimeouts")
IGNORE_CONFIG_CLIENT_VALUE("connInterfacesList")
IGNORE_CONFIG_CLIENT_VALUE("connRDMATimeouts")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAFragmentSize")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAKeyType")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaFragmentSize")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaBufNum")
IGNORE_CONFIG_CLIENT_VALUE("connRDMAMetaBufSize")
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheType")
IGNORE_CONFIG_CLIENT_VALUE("tunePagedIOBufSize")
IGNORE_CONFIG_CLIENT_VALUE("tunePagedIOBufNum")
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheBufSize")
IGNORE_CONFIG_CLIENT_VALUE("tuneFileCacheBufNum")
IGNORE_CONFIG_CLIENT_VALUE("tunePageCacheValidityMS")
IGNORE_CONFIG_CLIENT_VALUE("tuneAttribCacheValidityMS")
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxWriteWorks")
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWorks")
IGNORE_CONFIG_CLIENT_VALUE("tuneAllowMultiSetWrite")
IGNORE_CONFIG_CLIENT_VALUE("tuneAllowMultiSetRead")
IGNORE_CONFIG_CLIENT_VALUE("tunePathBufSize")
IGNORE_CONFIG_CLIENT_VALUE("tunePathBufNum")
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWriteNum")
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxReadWriteNodesNum")
IGNORE_CONFIG_CLIENT_VALUE("tuneMsgBufSize")
IGNORE_CONFIG_CLIENT_VALUE("tuneMsgBufNum")
IGNORE_CONFIG_CLIENT_VALUE("tuneRemoteFSync")
IGNORE_CONFIG_CLIENT_VALUE("tunePreferredMetaFile")
IGNORE_CONFIG_CLIENT_VALUE("tunePreferredStorageFile")
IGNORE_CONFIG_CLIENT_VALUE("tuneUseGlobalFileLocks")
IGNORE_CONFIG_CLIENT_VALUE("tuneRefreshOnGetAttr")
IGNORE_CONFIG_CLIENT_VALUE("tuneInodeBlockBits")
IGNORE_CONFIG_CLIENT_VALUE("tuneInodeBlockSize")
IGNORE_CONFIG_CLIENT_VALUE("tuneMaxClientMirrorSize") // was removed, kept here for compat
IGNORE_CONFIG_CLIENT_VALUE("tuneEarlyCloseResponse")
IGNORE_CONFIG_CLIENT_VALUE("tuneUseGlobalAppendLocks")
IGNORE_CONFIG_CLIENT_VALUE("tuneUseBufferedAppend")
IGNORE_CONFIG_CLIENT_VALUE("tuneStatFsCacheSecs")
IGNORE_CONFIG_CLIENT_VALUE("sysCacheInvalidationVersion")
IGNORE_CONFIG_CLIENT_VALUE("sysCreateHardlinksAsSymlinks")
IGNORE_CONFIG_CLIENT_VALUE("sysMountSanityCheckMS")
IGNORE_CONFIG_CLIENT_VALUE("sysSyncOnClose")
IGNORE_CONFIG_CLIENT_VALUE("sysSessionCheckOnClose")
IGNORE_CONFIG_CLIENT_VALUE("sysSessionChecksEnabled")
IGNORE_CONFIG_CLIENT_VALUE("sysTargetOfflineTimeoutSecs")
IGNORE_CONFIG_CLIENT_VALUE("sysInodeIDStyle")
IGNORE_CONFIG_CLIENT_VALUE("sysACLsEnabled")
IGNORE_CONFIG_CLIENT_VALUE("sysXAttrsEnabled")
IGNORE_CONFIG_CLIENT_VALUE("sysBypassFileAccessCheckOnMeta")
IGNORE_CONFIG_CLIENT_VALUE("sysXAttrsCheckCapabilities")
IGNORE_CONFIG_CLIENT_VALUE("tuneDirSubentryCacheValidityMS")
IGNORE_CONFIG_CLIENT_VALUE("tuneFileSubentryCacheValidityMS")
IGNORE_CONFIG_CLIENT_VALUE("tuneENOENTCacheValidityMS")
IGNORE_CONFIG_CLIENT_VALUE("tuneCoherentBuffers")
IGNORE_CONFIG_CLIENT_VALUE("sysFileEventLogMask")
IGNORE_CONFIG_CLIENT_VALUE("sysRenameEbusyAsXdev")
IGNORE_CONFIG_CLIENT_VALUE("tuneNumRetryWorkers")
IGNORE_CONFIG_CLIENT_VALUE("connHelperdPortTCP") // was removed, kept here for compat
if (testConfigMapKeyMatch(iter, "connInterfacesFile", addDashes))
connInterfacesFile = iter->second;
else if (testConfigMapKeyMatch(iter, "tuneNumWorkers", addDashes))
tuneNumWorkers = StringTk::strToUInt(iter->second);
else if (testConfigMapKeyMatch(iter, "tunePreferredNodesFile", addDashes))
tunePreferredNodesFile = iter->second;
else if (testConfigMapKeyMatch(iter, "tuneDbFragmentSize", addDashes))
tuneDbFragmentSize = StringTk::strToUInt64(iter->second.c_str());
else if (testConfigMapKeyMatch(iter, "tuneDentryCacheSize", addDashes))
tuneDentryCacheSize = StringTk::strToUInt64(iter->second.c_str());
else if (testConfigMapKeyMatch(iter, "runDaemonized", addDashes))
runDaemonized = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "databasePath", addDashes))
databasePath = iter->second;
else if (testConfigMapKeyMatch(iter, "overwriteDbFile", addDashes))
overwriteDbFile = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "testDatabasePath", addDashes))
testDatabasePath = iter->second;
else if (testConfigMapKeyMatch(iter, "databaseNumMaxConns", addDashes))
databaseNumMaxConns = StringTk::strHexToUInt(iter->second);
else if (testConfigMapKeyMatch(iter, "overrideRootMDS", addDashes))
overrideRootMDS = iter->second;
else if (testConfigMapKeyMatch(iter, "logStdFile", addDashes))
logStdFile = iter->second;
else if (testConfigMapKeyMatch(iter, "logOutFile", addDashes))
logOutFile = iter->second;
else if (testConfigMapKeyMatch(iter, "readOnly", addDashes))
readOnly = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "noFetch", addDashes))
noFetch = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "automatic", addDashes))
automatic = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "runOffline", addDashes))
runOffline = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "forceRestart", addDashes))
forceRestart = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "quotaEnabled", addDashes))
quotaEnabled = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "ignoreDBDiskSpace", addDashes))
ignoreDBDiskSpace = StringTk::strToBool(iter->second);
else if (testConfigMapKeyMatch(iter, "checkMalformedChunk", addDashes))
checkFsActions.set(CHECK_MALFORMED_CHUNK);
else if (testConfigMapKeyMatch(iter, "checkFilesWithMissingTargets", addDashes))
checkFsActions.set(CHECK_FILES_WITH_MISSING_TARGETS);
else if (testConfigMapKeyMatch(iter, "checkOrphanedDentryByIDFiles", addDashes))
checkFsActions.set(CHECK_ORPHANED_DENTRY_BYIDFILES);
else if (testConfigMapKeyMatch(iter, "checkDirEntriesWithBrokenIDFile", addDashes))
checkFsActions.set(CHECK_DIRENTRIES_WITH_BROKENIDFILE);
else if (testConfigMapKeyMatch(iter, "checkOrphanedChunk", addDashes))
checkFsActions.set(CHECK_ORPHANED_CHUNK);
else if (testConfigMapKeyMatch(iter, "checkChunksInWrongPath", addDashes))
checkFsActions.set(CHECK_CHUNKS_IN_WRONGPATH);
else if (testConfigMapKeyMatch(iter, "checkWrongInodeOwner", addDashes))
checkFsActions.set(CHECK_WRONG_INODE_OWNER);
else if (testConfigMapKeyMatch(iter, "checkWrongOwnerInDentry", addDashes))
checkFsActions.set(CHECK_WRONG_OWNER_IN_DENTRY);
else if (testConfigMapKeyMatch(iter, "checkOrphanedContDir", addDashes))
checkFsActions.set(CHECK_ORPHANED_CONT_DIR);
else if (testConfigMapKeyMatch(iter, "checkOrphanedDirInode", addDashes))
checkFsActions.set(CHECK_ORPHANED_DIR_INODE);
else if (testConfigMapKeyMatch(iter, "checkOrphanedFileInode", addDashes))
checkFsActions.set(CHECK_ORPHANED_FILE_INODE);
else if (testConfigMapKeyMatch(iter, "checkDanglingDentry", addDashes))
checkFsActions.set(CHECK_DANGLING_DENTRY);
else if (testConfigMapKeyMatch(iter, "checkMissingContDir", addDashes))
checkFsActions.set(CHECK_MISSING_CONT_DIR);
else if (testConfigMapKeyMatch(iter, "checkWrongFileAttribs", addDashes))
checkFsActions.set(CHECK_WRONG_FILE_ATTRIBS);
else if (testConfigMapKeyMatch(iter, "checkWrongDirAttribs", addDashes))
checkFsActions.set(CHECK_WRONG_DIR_ATTRIBS);
else if (testConfigMapKeyMatch(iter, "checkOldStyledHardlinks", addDashes))
checkFsActions.set(CHECK_OLD_STYLED_HARDLINKS);
else
{
// unknown element occurred
unknownElement = true;
if (enableException)
{
throw InvalidConfigException("The config argument '" + iter->first + "' is invalid");
}
}
// advance iterator (and remove handled element)
if (unknownElement)
{
// just skip the unknown element
iter++;
}
else
{
// remove this element from the map
iter = eraseFromConfigMap(iter);
}
}
}
void Config::initImplicitVals()
{
// tuneNumWorkers
if (!tuneNumWorkers)
tuneNumWorkers = BEEGFS_MAX(System::getNumOnlineCPUs() * 2, 4);
if (!tuneDbFragmentSize)
tuneDbFragmentSize = uint64_t(sysconf(_SC_PHYS_PAGES) ) * sysconf(_SC_PAGESIZE) / 2;
// just blindly assume that 384 bytes will be enough for a single cache entry. should be
if (!tuneDentryCacheSize)
tuneDentryCacheSize = tuneDbFragmentSize / 384;
// read in connAuthFile only if we are running as root.
// if not root, the program will abort anyway
if(!geteuid())
{
AbstractConfig::initConnAuthHash(connAuthFile, &connAuthHash);
}
}
std::string Config::createDefaultCfgFilename() const
{
struct stat statBuf;
const int statRes = stat(CONFIG_DEFAULT_CFGFILENAME, &statBuf);
if (!statRes && S_ISREG(statBuf.st_mode))
return CONFIG_DEFAULT_CFGFILENAME; // there appears to be a config file
return ""; // no default file otherwise
}

View File

@@ -0,0 +1,224 @@
#ifndef CONFIG_H_
#define CONFIG_H_
#include <common/app/config/AbstractConfig.h>
#include <bitset>
#define CONFIG_DEFAULT_CFGFILENAME "/etc/beegfs/beegfs-client.conf"
#define CONFIG_DEFAULT_LOGFILE "/var/log/beegfs-fsck.log"
#define CONFIG_DEFAULT_OUTFILE "/var/log/beegfs-fsck.out"
#define CONFIG_DEFAULT_DBPATH "/var/lib/beegfs/"
#define CONFIG_DEFAULT_TESTDBPATH "/tmp/beegfs-fsck/"
#define RUNMODE_HELP_KEY_STRING "--help" /* key for usage help */
#define __RUNMODES_SIZE \
( (sizeof(__RunModes) ) / (sizeof(RunModesElem) ) - 1)
/* -1 because last elem is NULL */
enum CheckFsActions
{
CHECK_MALFORMED_CHUNK = 0,
CHECK_FILES_WITH_MISSING_TARGETS = 1,
CHECK_ORPHANED_DENTRY_BYIDFILES = 2,
CHECK_DIRENTRIES_WITH_BROKENIDFILE = 3,
CHECK_ORPHANED_CHUNK = 4,
CHECK_CHUNKS_IN_WRONGPATH = 5,
CHECK_WRONG_INODE_OWNER = 6,
CHECK_WRONG_OWNER_IN_DENTRY = 7,
CHECK_ORPHANED_CONT_DIR = 8,
CHECK_ORPHANED_DIR_INODE = 9,
CHECK_ORPHANED_FILE_INODE = 10,
CHECK_DANGLING_DENTRY = 11,
CHECK_MISSING_CONT_DIR = 12,
CHECK_WRONG_FILE_ATTRIBS = 13,
CHECK_WRONG_DIR_ATTRIBS = 14,
CHECK_OLD_STYLED_HARDLINKS = 15,
CHECK_FS_ACTIONS_COUNT = 16
};
// Note: Keep in sync with __RunModes array
enum RunMode
{
RunMode_CHECKFS = 0,
RunMode_ENABLEQUOTA = 1,
RunMode_HELP = 2,
RunMode_INVALID = 3 /* not valid as index in RunModes array */
};
struct RunModesElem
{
const char* modeString;
enum RunMode runMode;
};
extern RunModesElem const __RunModes[];
class Config : public AbstractConfig
{
public:
Config(int argc, char** argv);
enum RunMode determineRunMode();
private:
// configurables
std::string connInterfacesFile;
unsigned tuneNumWorkers;
std::string tunePreferredNodesFile;
size_t tuneDbFragmentSize;
size_t tuneDentryCacheSize;
bool runDaemonized;
std::string databasePath;
bool overwriteDbFile;
// only relevant for unit testing, to give the used databasePath
std::string testDatabasePath;
unsigned databaseNumMaxConns;
std::string overrideRootMDS; // not tested well, should only be used by developers
// file for fsck output (not the log messages, but the output, which is also on the console)
std::string logOutFile;
bool readOnly;
bool noFetch;
bool automatic;
bool runOffline;
bool forceRestart;
bool quotaEnabled;
bool ignoreDBDiskSpace;
std::bitset<CHECK_FS_ACTIONS_COUNT> checkFsActions;
// internals
virtual void loadDefaults(bool addDashes) override;
virtual void applyConfigMap(bool enableException, bool addDashes) override;
virtual void initImplicitVals() override;
std::string createDefaultCfgFilename() const;
public:
// getters & setters
const StringMap* getUnknownConfigArgs() const
{
return getConfigMap();
}
const std::string& getConnInterfacesFile() const
{
return connInterfacesFile;
}
unsigned getTuneNumWorkers() const
{
return tuneNumWorkers;
}
size_t getTuneDbFragmentSize() const
{
return tuneDbFragmentSize;
}
size_t getTuneDentryCacheSize() const
{
return tuneDentryCacheSize;
}
const std::string& getTunePreferredNodesFile() const
{
return tunePreferredNodesFile;
}
bool getRunDaemonized() const
{
return runDaemonized;
}
const std::string& getDatabasePath() const
{
return databasePath;
}
bool getOverwriteDbFile() const
{
return overwriteDbFile;
}
const std::string& getTestDatabasePath() const
{
return testDatabasePath;
}
unsigned getDatabaseNumMaxConns() const
{
return databaseNumMaxConns;
}
std::string getOverrideRootMDS() const
{
return overrideRootMDS;
}
bool getReadOnly() const
{
return readOnly;
}
bool getNoFetch() const
{
return noFetch;
}
bool getAutomatic() const
{
return automatic;
}
const std::string& getLogOutFile() const
{
return logOutFile;
}
bool getRunOffline() const
{
return runOffline;
}
bool getForceRestart() const
{
return forceRestart;
}
bool getQuotaEnabled() const
{
return quotaEnabled;
}
bool getIgnoreDBDiskSpace() const
{
return ignoreDBDiskSpace;
}
std::bitset<CHECK_FS_ACTIONS_COUNT> getCheckFsActions() const
{
return checkFsActions;
}
void disableAutomaticRepairMode()
{
this->automatic = false;
}
void setReadOnly()
{
this->readOnly = true;
}
};
#endif /*CONFIG_H_*/