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

View File

@@ -0,0 +1,213 @@
#include "AdjustChunkPermissionsMsgEx.h"
#include <program/Program.h>
#include <common/net/message/storage/attribs/SetLocalAttrMsg.h>
#include <common/net/message/storage/attribs/SetLocalAttrRespMsg.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <components/worker/SetChunkFileAttribsWork.h>
bool AdjustChunkPermissionsMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("Incoming AdjustChunkPermissionsMsg");
MetaStore *metaStore = Program::getApp()->getMetaStore();
unsigned hashDirNum = this->getHashDirNum();
unsigned maxEntries = this->getMaxEntries();
int64_t lastHashDirOffset = this->getLastHashDirOffset();
int64_t lastContDirOffset = this->getLastContDirOffset();
std::string currentContDirID = this->getCurrentContDirID();
int64_t newHashDirOffset = 0;
int64_t newContDirOffset = 0;
unsigned errorCount = 0;
unsigned readOutEntries = 0;
bool hasNext;
if ( currentContDirID.empty() )
{
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(), lastHashDirOffset,
&currentContDirID, &newHashDirOffset);
if ( hasNext )
{
lastHashDirOffset = newHashDirOffset;
}
}
else
hasNext = true;
while ( hasNext )
{
std::string parentID = currentContDirID;
unsigned remainingEntries = maxEntries - readOutEntries;
StringList entryNames;
bool parentDirInodeIsTemp = false;
FileIDLock dirLock;
if (getIsBuddyMirrored())
dirLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), parentID, false};
DirInode* parentDirInode = metaStore->referenceDir(parentID, getIsBuddyMirrored(), true);
// it could be, that parentDirInode does not exist
// in fsck we create a temporary inode for this case
if ( unlikely(!parentDirInode) )
{
log.log(
Log_NOTICE,
"Could not reference directory. EntryID: " + parentID
+ " => using temporary directory inode ");
// create temporary inode
int mode = S_IFDIR | S_IRWXU;
UInt16Vector stripeTargets;
Raid0Pattern stripePattern(0, stripeTargets, 0);
parentDirInode = new DirInode(parentID, mode, 0, 0,
Program::getApp()->getLocalNode().getNumID(), stripePattern, getIsBuddyMirrored());
parentDirInodeIsTemp = true;
}
if ( parentDirInode->listIncremental(lastContDirOffset, remainingEntries, &entryNames,
&newContDirOffset) == FhgfsOpsErr_SUCCESS )
{
lastContDirOffset = newContDirOffset;
readOutEntries += entryNames.size();
}
else
{
log.log(Log_WARNING, "Could not list contents of directory. EntryID: " + parentID);
}
// actually process the entries; for the dentry part we only need to know if it is a file
// with inlined inode data
for ( StringListIter namesIter = entryNames.begin(); namesIter != entryNames.end();
namesIter++ )
{
std::string filename = MetaStorageTk::getMetaDirEntryPath(
getIsBuddyMirrored()
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
: Program::getApp()->getDentriesPath()->str(), parentID) + "/" + *namesIter;
EntryInfo entryInfo;
FileInodeStoreData inodeDiskData;
auto [getEntryRes, isFileOpen] = metaStore->getEntryData(parentDirInode, *namesIter, &entryInfo,
&inodeDiskData);
inodeDiskData.setDynamicOrigParentEntryID(parentID);
if (getEntryRes == FhgfsOpsErr_SUCCESS ||
getEntryRes == FhgfsOpsErr_DYNAMICATTRIBSOUTDATED )
{
DirEntryType entryType = entryInfo.getEntryType();
// we only care if inode data is present
if ( (DirEntryType_ISFILE(entryType)) && (entryInfo.getIsInlined() ) )
{
const std::string& inodeID = inodeDiskData.getEntryID();
unsigned userID = inodeDiskData.getInodeStatData()->getUserID();
unsigned groupID = inodeDiskData.getInodeStatData()->getGroupID();
StripePattern* pattern = inodeDiskData.getStripePattern();
PathInfo pathInfo;
inodeDiskData.getPathInfo(&pathInfo);
if ( !this->sendSetAttrMsg(inodeID, userID, groupID, &pathInfo, pattern) )
errorCount++;
}
}
else
{
log.log(Log_WARNING, "Unable to create dir entry from entry with name " + *namesIter
+ " in directory with ID " + parentID);
}
}
if ( parentDirInodeIsTemp )
SAFE_DELETE(parentDirInode);
else
metaStore->releaseDir(parentID);
if ( entryNames.size() < remainingEntries )
{
// directory is at the end => proceed with next
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(),
lastHashDirOffset, &currentContDirID, &newHashDirOffset);
if ( hasNext )
{
lastHashDirOffset = newHashDirOffset;
lastContDirOffset = 0;
}
}
else
{
// there are more to come, but we need to exit the loop now, because maxCount is reached
hasNext = false;
}
}
ctx.sendResponse(
AdjustChunkPermissionsRespMsg(readOutEntries, currentContDirID, lastHashDirOffset,
lastContDirOffset, errorCount) );
return true;
}
bool AdjustChunkPermissionsMsgEx::sendSetAttrMsg(const std::string& entryID, unsigned userID,
unsigned groupID, PathInfo* pathInfo, StripePattern* pattern)
{
const char* logContext = "AdjustChunkPermissionsMsgEx::sendSetAttrMsg";
MultiWorkQueue* slaveQueue = Program::getApp()->getCommSlaveQueue();
int validAttribs = SETATTR_CHANGE_USERID | SETATTR_CHANGE_GROUPID; // only interested in these
SettableFileAttribs attribs;
attribs.userID = userID;
attribs.groupID = groupID;
const UInt16Vector* stripeTargets = pattern->getStripeTargetIDs();
size_t numTargetWorks = stripeTargets->size();
FhgfsOpsErrVec nodeResults(numTargetWorks);
SynchronizedCounter counter;
// generate work for storage targets...
for(size_t i=0; i < numTargetWorks; i++)
{
SetChunkFileAttribsWork* work = new SetChunkFileAttribsWork(
entryID, validAttribs, &attribs, false, pattern, (*stripeTargets)[i], pathInfo,
NULL, &(nodeResults[i]), &counter);
work->setQuotaChown(true);
work->setMsgUserID(getMsgHeaderUserID() );
slaveQueue->addDirectWork(work);
}
// wait for work completion...
counter.waitForCount(numTargetWorks);
// check target results...
for(size_t i=0; i < numTargetWorks; i++)
{
if(unlikely(nodeResults[i] != FhgfsOpsErr_SUCCESS) )
{
LogContext(logContext).log(Log_WARNING,
"Problems occurred during setting of chunk file attribs. "
"fileID: " + entryID );
return false;
}
}
return true;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <common/net/message/fsck/AdjustChunkPermissionsMsg.h>
#include <common/net/message/fsck/AdjustChunkPermissionsRespMsg.h>
#include <common/storage/PathInfo.h>
#include <common/storage/striping/StripePattern.h>
class AdjustChunkPermissionsMsgEx : public AdjustChunkPermissionsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
private:
bool sendSetAttrMsg(const std::string& entryID, unsigned userID, unsigned groupID,
PathInfo* pathInfo, StripePattern* pattern);
};

View File

@@ -0,0 +1,38 @@
#include <program/Program.h>
#include <common/net/message/fsck/CheckAndRepairDupInodeRespMsg.h>
#include "CheckAndRepairDupInodeMsgEx.h"
bool CheckAndRepairDupInodeMsgEx::processIncoming(ResponseContext& ctx)
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
StringList failedIDList;
for (const auto& inode : getDuplicateInodes())
{
const std::string& entryID = inode.getID();
const std::string& parentEntryID = inode.getParentDirID();
const bool isBuddyMirrored = inode.getIsBuddyMirrored();
FileIDLock dirLock = {entryLockStore, parentEntryID, true};
FileIDLock fileLock = {entryLockStore, entryID, true};
EntryInfo fileInfo(NumNodeID(0), parentEntryID, entryID, std::string(""), DirEntryType_REGULARFILE, 0);
fileInfo.setBuddyMirroredFlag(isBuddyMirrored);
DirInode* parentDir = metaStore->referenceDir(parentEntryID, isBuddyMirrored, true);
FhgfsOpsErr repairRes = metaStore->checkAndRepairDupFileInode(*parentDir, &fileInfo);
if (repairRes != FhgfsOpsErr_SUCCESS)
{
failedIDList.push_back(entryID);
}
metaStore->releaseDir(parentDir->getID());
}
ctx.sendResponse(CheckAndRepairDupInodeRespMsg(std::move(failedIDList)));
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/fsck/CheckAndRepairDupInodeMsg.h>
class CheckAndRepairDupInodeMsgEx : public CheckAndRepairDupInodeMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,60 @@
#include "CreateDefDirInodesMsgEx.h"
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool CreateDefDirInodesMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("CreateDefDirInodesMsg incoming");
App* app = Program::getApp();
Config* cfg = app->getConfig();
StringList failedInodeIDs;
FsckDirInodeList createdInodes;
for (auto it = items.begin(); it != items.end(); ++it)
{
const std::string& inodeID = std::get<0>(*it);
const bool isBuddyMirrored = std::get<1>(*it);
int mode = S_IFDIR | S_IRWXU;
unsigned userID = 0; // root
unsigned groupID = 0; // root
const NumNodeID ownerNodeID = isBuddyMirrored
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID())
: app->getLocalNode().getNumID();
UInt16Vector stripeTargets;
unsigned defaultChunkSize = cfg->getTuneDefaultChunkSize();
unsigned defaultNumStripeTargets = cfg->getTuneDefaultNumStripeTargets();
Raid0Pattern stripePattern(defaultChunkSize, stripeTargets, defaultNumStripeTargets);
// we try to create a new directory inode, with default values
FileIDLock dirLock;
if (isBuddyMirrored)
dirLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), inodeID, true};
DirInode dirInode(inodeID, mode, userID, groupID, ownerNodeID, stripePattern,
isBuddyMirrored);
if ( dirInode.storeAsReplacementFile(inodeID) == FhgfsOpsErr_SUCCESS )
{
// try to refresh the metainfo (maybe a .cont directory was already present)
dirInode.refreshMetaInfo();
StatData statData;
dirInode.getStatData(statData);
FsckDirInode fsckDirInode(inodeID, "", NumNodeID(), ownerNodeID, statData.getFileSize(),
statData.getNumHardlinks(), stripeTargets, FsckStripePatternType_RAID0,
ownerNodeID, isBuddyMirrored, true, false);
createdInodes.push_back(fsckDirInode);
}
else
failedInodeIDs.push_back(inodeID);
}
ctx.sendResponse(CreateDefDirInodesRespMsg(&failedInodeIDs, &createdInodes) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/storage/striping/Raid0Pattern.h>
#include <common/net/message/fsck/CreateDefDirInodesMsg.h>
#include <common/net/message/fsck/CreateDefDirInodesRespMsg.h>
class CreateDefDirInodesMsgEx : public CreateDefDirInodesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,77 @@
#include "CreateEmptyContDirsMsgEx.h"
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool CreateEmptyContDirsMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "CreateEmptyContDirsMsg incoming";
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
StringList failedIDs;
for (auto iter = items.begin(); iter != items.end(); iter++)
{
const std::string& dirID = std::get<0>(*iter);
const bool isBuddyMirrored = std::get<1>(*iter);
std::string contentsDirStr = MetaStorageTk::getMetaDirEntryPath(
isBuddyMirrored
? app->getBuddyMirrorDentriesPath()->str()
: app->getDentriesPath()->str(), dirID);
// create contents directory
int mkRes = mkdir(contentsDirStr.c_str(), 0755);
if ( mkRes != 0 )
{ // error
LOG(GENERAL, ERR, "Unable to create contents directory.", contentsDirStr, sysErr);
failedIDs.push_back(dirID);
continue;
}
// create the dirEntryID directory, which allows access to inlined inodes via dirID access
std::string contentsDirIDStr = MetaStorageTk::getMetaDirEntryIDPath(contentsDirStr);
int mkDirIDRes = mkdir(contentsDirIDStr.c_str(), 0755);
if ( mkDirIDRes != 0 )
{ // error
LOG(GENERAL, ERR, "Unable to create dirEntryID directory.", contentsDirIDStr, sysErr);
failedIDs.push_back(dirID);
continue;
}
FileIDLock lock;
if (isBuddyMirrored)
lock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(), dirID, true};
// update the dir attribs
DirInode* dirInode = metaStore->referenceDir(dirID, isBuddyMirrored, true);
if (!dirInode)
{
LOG(GENERAL, ERR, "Unable to reference directory.", dirID);
failedIDs.push_back(dirID);
continue;
}
FhgfsOpsErr refreshRes = dirInode->refreshMetaInfo();
if (refreshRes != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).log(Log_NOTICE, "Unable to refresh contents directory metadata: "
+ contentsDirStr + ". " + "SysErr: " + System::getErrString());
}
metaStore->releaseDir(dirID);
}
ctx.sendResponse(CreateEmptyContDirsRespMsg(&failedIDs) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/storage/striping/Raid0Pattern.h>
#include <common/net/message/fsck/CreateEmptyContDirsMsg.h>
#include <common/net/message/fsck/CreateEmptyContDirsRespMsg.h>
class CreateEmptyContDirsMsgEx : public CreateEmptyContDirsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,66 @@
#include "DeleteDirEntriesMsgEx.h"
#include <program/Program.h>
#include <common/fsck/FsckDirEntry.h>
#include <toolkit/BuddyCommTk.h>
#include <boost/lexical_cast.hpp>
bool DeleteDirEntriesMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("DeleteDirEntriesMsgEx");
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
FsckDirEntryList& entries = getEntries();
FsckDirEntryList failedEntries;
for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ )
{
const std::string& parentID = iter->getParentDirID();
const std::string& entryName = iter->getName();
FsckDirEntryType dirEntryType = iter->getEntryType();
FileIDLock dirLock;
ParentNameLock dentryLock;
if (iter->getIsBuddyMirrored())
{
dirLock = {entryLockStore, parentID, true};
dentryLock = {entryLockStore, parentID, entryName};
}
DirInode* parentDirInode = metaStore->referenceDir(parentID, iter->getIsBuddyMirrored(),
true);
if (!parentDirInode)
{
log.log(3,"Failed to delete directory entry; ParentID: " + parentID + "; EntryName: " +
entryName + " - ParentID does not exist");
failedEntries.push_back(*iter);
continue;
}
FhgfsOpsErr unlinkRes;
if (FsckDirEntryType_ISDIR(dirEntryType))
unlinkRes = parentDirInode->removeDir(entryName, NULL);
else
unlinkRes = parentDirInode->unlinkDirEntry(entryName, NULL,
DirEntry_UNLINK_ID_AND_FILENAME);
metaStore->releaseDir(parentID);
if (unlinkRes != FhgfsOpsErr_SUCCESS )
{
log.logErr("Failed to delete directory entry; ParentID: " + parentID + "; EntryName: " +
entryName + "; Err: " + boost::lexical_cast<std::string>(unlinkRes));
failedEntries.push_back(*iter);
}
}
ctx.sendResponse(DeleteDirEntriesRespMsg(&failedEntries) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/DeleteDirEntriesMsg.h>
#include <common/net/message/fsck/DeleteDirEntriesRespMsg.h>
class DeleteDirEntriesMsgEx : public DeleteDirEntriesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,77 @@
#include "FixInodeOwnersInDentryMsgEx.h"
#include <common/storage/striping/Raid0Pattern.h>
#include <common/fsck/FsckDirEntry.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool FixInodeOwnersInDentryMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("FixInodeOwnersInDentryMsgEx");
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
FsckDirEntryList& dentries = getDentries();
FsckDirEntryList failedEntries;
FsckDirEntryListIter dentryIter = dentries.begin();
NumNodeIDListIter ownerIter = getOwners().begin();
while (dentryIter != dentries.end() )
{
const std::string& parentID = dentryIter->getParentDirID();
const std::string& entryName = dentryIter->getName();
ParentNameLock lock;
if (dentryIter->getIsBuddyMirrored())
lock = {entryLockStore, parentID, entryName};
bool parentDirInodeIsTemp = false;
DirInode* parentDirInode = metaStore->referenceDir(parentID,
dentryIter->getIsBuddyMirrored(), true);
// it could be, that parentDirInode does not exist
// in fsck we create a temporary inode for this case, so that we can modify the dentry
// hopefully, the inode itself will get fixed later
if (unlikely(!parentDirInode))
{
log.log(Log_NOTICE,
"Failed to update directory entry. Parent directory could not be "
"referenced. parentID: " + parentID + " entryName: " + entryName
+ " => Using temporary inode");
// create temporary inode
int mode = S_IFDIR | S_IRWXU;
UInt16Vector stripeTargets;
Raid0Pattern stripePattern(0, stripeTargets, 0);
parentDirInode = new DirInode(parentID, mode, 0, 0,
Program::getApp()->getLocalNode().getNumID(), stripePattern,
dentryIter->getIsBuddyMirrored());
parentDirInodeIsTemp = true;
}
FhgfsOpsErr updateRes = parentDirInode->setOwnerNodeID(entryName, *ownerIter);
if (updateRes != FhgfsOpsErr_SUCCESS )
{
log.log(Log_WARNING, "Failed to update directory entry. parentID: " + parentID +
" entryName: " + entryName);
failedEntries.push_back(*dentryIter);
}
if (parentDirInodeIsTemp)
SAFE_DELETE(parentDirInode);
else
metaStore->releaseDir(parentID);
dentryIter++;
ownerIter++;
}
ctx.sendResponse(FixInodeOwnersInDentryRespMsg(&failedEntries) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/FixInodeOwnersInDentryMsg.h>
#include <common/net/message/fsck/FixInodeOwnersInDentryRespMsg.h>
class FixInodeOwnersInDentryMsgEx : public FixInodeOwnersInDentryMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,51 @@
#include "FixInodeOwnersMsgEx.h"
#include <common/fsck/FsckDirEntry.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool FixInodeOwnersMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "FixInodeOwnersMsgEx incoming";
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
FsckDirInodeList& inodes = getInodes();
FsckDirInodeList failedInodes;
for ( FsckDirInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++ )
{
const std::string& entryID = iter->getID();
NumNodeID ownerNodeID = iter->getOwnerNodeID();
FileIDLock lock;
if (iter->getIsBuddyMirrored())
lock = {entryLockStore, entryID, true};
DirInode* dirInode = metaStore->referenceDir(entryID, iter->getIsBuddyMirrored(), true);
if (unlikely(!dirInode))
{
LogContext(logContext).log(Log_WARNING, "Failed to update directory inode. Inode could"
" not be referenced. entryID: " + entryID);
continue; // continue to next entry
}
bool updateRes = dirInode->setOwnerNodeID(ownerNodeID);
metaStore->releaseDir(entryID);
if (!updateRes)
{
LogContext(logContext).log(Log_WARNING, "Failed to update directory inode. entryID: "
+ entryID);
failedInodes.push_back(*iter);
}
}
ctx.sendResponse(FixInodeOwnersRespMsg(&failedInodes) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/FixInodeOwnersMsg.h>
#include <common/net/message/fsck/FixInodeOwnersRespMsg.h>
class FixInodeOwnersMsgEx : public FixInodeOwnersMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,34 @@
#include <components/ModificationEventFlusher.h>
#include <program/Program.h>
#include "FsckSetEventLoggingMsgEx.h"
bool FsckSetEventLoggingMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("FsckSetEventLoggingMsg incoming");
App* app = Program::getApp();
ModificationEventFlusher* flusher = app->getModificationEventFlusher();
bool result;
bool loggingEnabled;
bool missedEvents;
bool enableLogging = this->getEnableLogging();
if (enableLogging)
{
loggingEnabled = flusher->enableLogging(getPortUDP(), getNicList(), getForceRestart());
result = true; // (always true when logging is enabled)
missedEvents = true; // (value ignored when logging is enabled)
}
else
{ // disable logging
result = flusher->disableLogging();
loggingEnabled = false; // (value ignored when logging is disabled)
missedEvents = flusher->getFsckMissedEvent();
}
ctx.sendResponse(FsckSetEventLoggingRespMsg(result, loggingEnabled, missedEvents));
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/fsck/FsckSetEventLoggingMsg.h>
#include <common/net/message/fsck/FsckSetEventLoggingRespMsg.h>
class FsckSetEventLoggingMsgEx : public FsckSetEventLoggingMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,108 @@
#include "LinkToLostAndFoundMsgEx.h"
#include <common/net/message/fsck/RemoveInodesMsg.h>
#include <common/net/message/fsck/RemoveInodesRespMsg.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool LinkToLostAndFoundMsgEx::processIncoming(ResponseContext& ctx)
{
if (FsckDirEntryType_ISDIR(this->getEntryType()))
{
FsckDirEntryList createdDirEntries;
FsckDirInodeList failedInodes;
linkDirInodes(&failedInodes, &createdDirEntries);
ctx.sendResponse(LinkToLostAndFoundRespMsg(&failedInodes, &createdDirEntries) );
}
else
{
LOG(COMMUNICATION, ERR, "LinkToLostAndFoundMsg received for non-inlined file inode.",
("from", ctx.peerName()));
return false;
}
return true;
}
void LinkToLostAndFoundMsgEx::linkDirInodes(FsckDirInodeList* outFailedInodes,
FsckDirEntryList* outCreatedDirEntries)
{
const char* logContext = "LinkToLostAndFoundMsgEx (linkDirInodes)";
NumNodeID localNodeNumID = Program::getApp()->getLocalNode().getNumID();
FsckDirInodeList& dirInodes = getDirInodes();
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
EntryInfo* lostAndFoundInfo = this->getLostAndFoundInfo();
DirInode* lostAndFoundDir = metaStore->referenceDir(lostAndFoundInfo->getEntryID(),
lostAndFoundInfo->getIsBuddyMirrored(), true);
if ( !lostAndFoundDir )
{
*outFailedInodes = dirInodes;
return;
}
else
{
for ( FsckDirInodeListIter iter = dirInodes.begin(); iter != dirInodes.end(); iter++ )
{
const std::string& entryID = iter->getID();
NumNodeID ownerNodeID = iter->getOwnerNodeID();
DirEntryType entryType = DirEntryType_DIRECTORY;
DirEntry newDirEntry(entryType, entryID, entryID, ownerNodeID);
FileIDLock lock;
if (iter->getIsBuddyMirrored())
{
lock = {entryLockStore, entryID, true};
newDirEntry.setBuddyMirrorFeatureFlag();
}
bool makeRes = lostAndFoundDir->makeDirEntry(newDirEntry);
// stat the new file to get device and inode information
std::string filename = MetaStorageTk::getMetaDirEntryPath(
lostAndFoundInfo->getIsBuddyMirrored()
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
: Program::getApp()->getDentriesPath()->str(),
lostAndFoundInfo->getEntryID()) + "/" + entryID;
struct stat statBuf;
int statRes = stat(filename.c_str(), &statBuf);
int saveDevice;
uint64_t saveInode;
if ( likely(!statRes) )
{
saveDevice = statBuf.st_dev;
saveInode = statBuf.st_ino;
}
else
{
saveDevice = 0;
saveInode = 0;
LogContext(logContext).log(Log_CRITICAL,
"Could not stat dir entry file; entryID: " + entryID + ";filename: " + filename);
}
if ( makeRes != FhgfsOpsErr_SUCCESS )
outFailedInodes->push_back(*iter);
else
{
std::string parentID = lostAndFoundInfo->getEntryID();
FsckDirEntry newFsckDirEntry(entryID, entryID, parentID, localNodeNumID,
ownerNodeID, FsckDirEntryType_DIRECTORY, false, localNodeNumID,
saveDevice, saveInode, lostAndFoundInfo->getIsBuddyMirrored());
outCreatedDirEntries->push_back(newFsckDirEntry);
}
}
lostAndFoundDir->refreshMetaInfo();
metaStore->releaseDir(lostAndFoundInfo->getEntryID() );
}
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/LinkToLostAndFoundMsg.h>
#include <common/net/message/fsck/LinkToLostAndFoundRespMsg.h>
#include <common/net/message/storage/creating/MkDirMsg.h>
#include <common/net/message/storage/creating/MkDirRespMsg.h>
#include <common/storage/StorageErrors.h>
#include <dirent.h>
class LinkToLostAndFoundMsgEx : public LinkToLostAndFoundMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
private:
void linkDirInodes(FsckDirInodeList* outFailedInodes, FsckDirEntryList* outCreatedDirEntries);
void linkFileInodes(FsckFileInodeList* outFailedInodes,
FsckDirEntryList* outCreatedDirEntries);
FhgfsOpsErr deleteInode(std::string& entryID, uint16_t ownerNodeID);
};

View File

@@ -0,0 +1,141 @@
#include "RecreateDentriesMsgEx.h"
#include <common/fsck/FsckDirEntry.h>
#include <common/fsck/FsckFsID.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool RecreateDentriesMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("RecreateDentriesMsgEx");
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
EntryLockStore* entryLockStore = app->getMirroredSessions()->getEntryLockStore();
FsckFsIDList& fsIDs = getFsIDs();
FsckFsIDList failedCreates;
FsckDirEntryList createdDentries;
FsckFileInodeList createdInodes;
for ( FsckFsIDListIter iter = fsIDs.begin(); iter != fsIDs.end(); iter++ )
{
NumNodeID localNodeID = iter->getIsBuddyMirrored()
? NumNodeID(app->getMetaBuddyGroupMapper()->getLocalGroupID())
: app->getLocalNodeNumID();
std::string parentPath = MetaStorageTk::getMetaDirEntryPath(
iter->getIsBuddyMirrored()
? app->getBuddyMirrorDentriesPath()->str()
: app->getDentriesPath()->str(), iter->getParentDirID());
std::string dirEntryIDFilePath = MetaStorageTk::getMetaDirEntryIDPath(parentPath) + "/"
+ iter->getID();
// the name is lost, so we take the ID as new name
std::string dirEntryNameFilePath = parentPath + "/" + iter->getID();
// before we link, let's see if we can open the parent dir, otherwise we should not mess
// around here
const std::string& dirID = iter->getParentDirID();
FileIDLock dirLock;
ParentNameLock dentryLock;
if (iter->getIsBuddyMirrored())
{
dirLock = {entryLockStore, dirID, true};
dentryLock = {entryLockStore, dirID, iter->getID()};
}
DirInode* parentDirInode = metaStore->referenceDir(dirID, iter->getIsBuddyMirrored(), false);
if (!parentDirInode)
{
log.logErr("Unable to reference parent directory; ID: " + iter->getParentDirID());
failedCreates.push_back(*iter);
continue;
}
// link the dentry-by-name file
int linkRes = link(dirEntryIDFilePath.c_str(), dirEntryNameFilePath.c_str());
if ( linkRes )
{
// error occured while linking
log.logErr(
"Failed to link dentry file; ParentID: " + iter->getParentDirID() + "; ID: "
+ iter->getID());
failedCreates.push_back(*iter);
metaStore->releaseDir(dirID);
continue;
}
// linking was OK => gather dentry (and inode) data, so fsck can add it
DirEntry dirEntry(iter->getID());
bool getRes = parentDirInode->getDentry(iter->getID(), dirEntry);
if (!getRes)
{
log.logErr(
"Could not read the created dentry file; ParentID: " + iter->getParentDirID() + "; ID: "
+ iter->getID());
failedCreates.push_back(*iter);
metaStore->releaseDir(dirID);
continue;
}
// create the FsckDirEntry
FsckDirEntry fsckDirEntry(dirEntry.getID(), dirEntry.getName(), iter->getParentDirID(),
localNodeID, localNodeID,
FsckTk::DirEntryTypeToFsckDirEntryType(dirEntry.getEntryType()), true, localNodeID,
iter->getSaveDevice(), iter->getSaveInode(), iter->getIsBuddyMirrored());
createdDentries.push_back(fsckDirEntry);
// inlined inode data should be present, because otherwise dentry-by-id file would not
// exist, and we could not get this far
FileInodeStoreData* inodeData = dirEntry.getInodeStoreData();
if ( inodeData )
{
int pathInfoFlags;
if (inodeData->getOrigFeature() == FileInodeOrigFeature_TRUE)
pathInfoFlags = PATHINFO_FEATURE_ORIG;
else
pathInfoFlags = PATHINFO_FEATURE_ORIG_UNKNOWN;
PathInfo pathInfo(inodeData->getOrigUID(), inodeData->getOrigParentEntryID(),
pathInfoFlags);
UInt16Vector targetIDs;
unsigned chunkSize;
FsckStripePatternType fsckStripePatternType = FsckTk::stripePatternToFsckStripePattern(
inodeData->getPattern(), &chunkSize, &targetIDs);
FsckFileInode fsckFileInode(inodeData->getEntryID(), iter->getParentDirID(),
localNodeID, pathInfo, inodeData->getInodeStatData(),
inodeData->getInodeStatData()->getNumBlocks(), targetIDs, fsckStripePatternType,
chunkSize, localNodeID, iter->getSaveInode(), iter->getSaveDevice(), true,
iter->getIsBuddyMirrored(), true, false);
createdInodes.push_back(fsckFileInode);
}
else
{
log.logErr(
"No inlined inode data found; parentID: " + iter->getParentDirID() + "; ID: "
+ iter->getID());
}
metaStore->releaseDir(dirID);
}
ctx.sendResponse(RecreateDentriesRespMsg(&failedCreates, &createdDentries, &createdInodes) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/RecreateDentriesMsg.h>
#include <common/net/message/fsck/RecreateDentriesRespMsg.h>
class RecreateDentriesMsgEx : public RecreateDentriesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,65 @@
#include "RecreateFsIDsMsgEx.h"
#include <common/fsck/FsckDirEntry.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool RecreateFsIDsMsgEx::processIncoming(ResponseContext& ctx)
{
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
LogContext log("RecreateFsIDsMsgEx");
FsckDirEntryList& entries = getEntries();
FsckDirEntryList failedEntries;
for ( FsckDirEntryListIter iter = entries.begin(); iter != entries.end(); iter++ )
{
const std::string& parentID = iter->getParentDirID();
const std::string& entryName = iter->getName();
const std::string& entryID = iter->getID();
std::string dirEntryPath = MetaStorageTk::getMetaDirEntryPath(
iter->getIsBuddyMirrored()
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
: Program::getApp()->getDentriesPath()->str(), parentID);
std::string dirEntryIDFilePath = MetaStorageTk::getMetaDirEntryIDPath(dirEntryPath) +
"/" + entryID;
std::string dirEntryNameFilePath = dirEntryPath + "/" + entryName;
FileIDLock dirLock(entryLockStore, parentID, true);
ParentNameLock dentryLock(entryLockStore, parentID, entryName);
FileIDLock fileLock(entryLockStore, entryID, true);
// delete the old dentry-by-id file link (if one existed)
int removeRes = unlink(dirEntryIDFilePath.c_str());
if ( (removeRes) && (errno != ENOENT) )
{
log.logErr(
"Failed to recreate dentry-by-id file for directory entry; ParentID: " + parentID
+ "; EntryName: " + entryName
+ " - Could not delete old, faulty dentry-by-id file link");
failedEntries.push_back(*iter);
continue;
}
// link a new one
int linkRes = link(dirEntryNameFilePath.c_str(), dirEntryIDFilePath.c_str());
if ( linkRes )
{
log.logErr(
"Failed to recreate dentry-by-id file for directory entry; ParentID: " + parentID
+ "; EntryName: " + entryName + " - File could not be linked");
failedEntries.push_back(*iter);
continue;
}
}
ctx.sendResponse(RecreateFsIDsRespMsg(&failedEntries) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/RecreateFsIDsMsg.h>
#include <common/net/message/fsck/RecreateFsIDsRespMsg.h>
class RecreateFsIDsMsgEx : public RecreateFsIDsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,44 @@
#include <program/Program.h>
#include <common/net/message/fsck/RemoveInodesRespMsg.h>
#include <common/toolkit/ZipIterator.h>
#include <toolkit/BuddyCommTk.h>
#include "RemoveInodesMsgEx.h"
bool RemoveInodesMsgEx::processIncoming(ResponseContext& ctx)
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
StringList failedIDList;
for (auto it = items.begin(); it != items.end(); ++it)
{
const std::string& entryID = std::get<0>(*it);
const DirEntryType entryType = std::get<1>(*it);
const bool isBuddyMirrored = std::get<2>(*it);
FhgfsOpsErr rmRes;
FileIDLock dirLock;
FileIDLock fileLock;
if (entryType == DirEntryType_DIRECTORY)
{
dirLock = {entryLockStore, entryID, true};
rmRes = metaStore->removeDirInode(entryID, isBuddyMirrored);
}
else
{
fileLock = {entryLockStore, entryID, true};
rmRes = metaStore->fsckUnlinkFileInode(entryID, isBuddyMirrored);
}
if (rmRes != FhgfsOpsErr_SUCCESS)
failedIDList.push_back(entryID);
}
ctx.sendResponse(RemoveInodesRespMsg(std::move(failedIDList)));
return true;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include <common/net/message/fsck/RemoveInodesMsg.h>
class RemoveInodesMsgEx : public RemoveInodesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,269 @@
#include "RetrieveDirEntriesMsgEx.h"
#include <common/storage/striping/Raid0Pattern.h>
#include <net/msghelpers/MsgHelperStat.h>
#include <program/Program.h>
bool RetrieveDirEntriesMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("Incoming RetrieveDirEntriesMsg");
unsigned hashDirNum = getHashDirNum();
std::string currentContDirID = getCurrentContDirID();
unsigned maxOutEntries = getMaxOutEntries();
int64_t lastContDirOffset = getLastContDirOffset();
int64_t lastHashDirOffset = getLastHashDirOffset();
int64_t newHashDirOffset;
int64_t newContDirOffset;
FsckContDirList contDirsOutgoing;
FsckDirEntryList dirEntriesOutgoing;
FsckFileInodeList inlinedFileInodesOutgoing;
unsigned readOutEntries = 0;
NumNodeID localNodeNumID = getIsBuddyMirrored()
? NumNodeID(Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID())
: Program::getApp()->getLocalNode().getNumID();
MetaStore* metaStore = Program::getApp()->getMetaStore();
MirrorBuddyGroupMapper* bgm = Program::getApp()->getMetaBuddyGroupMapper();
if (getIsBuddyMirrored() &&
(bgm->getLocalBuddyGroup().secondTargetID
== Program::getApp()->getLocalNode().getNumID().val()
|| bgm->getLocalGroupID() == 0))
{
ctx.sendResponse(
RetrieveDirEntriesRespMsg(&contDirsOutgoing, &dirEntriesOutgoing,
&inlinedFileInodesOutgoing, currentContDirID, lastHashDirOffset, lastContDirOffset));
return true;
}
bool hasNext;
if ( currentContDirID.empty() )
{
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(), lastHashDirOffset,
&currentContDirID, &newHashDirOffset);
if ( hasNext )
{
lastHashDirOffset = newHashDirOffset;
// we found a new .cont directory => send it to fsck
FsckContDir contDir(currentContDirID, localNodeNumID, getIsBuddyMirrored());
contDirsOutgoing.push_back(contDir);
}
}
else
hasNext = true;
while ( hasNext )
{
std::string parentID = currentContDirID;
unsigned remainingOutNames = maxOutEntries - readOutEntries;
StringList entryNames;
bool parentDirInodeIsTemp = false;
DirInode* parentDirInode = metaStore->referenceDir(parentID, getIsBuddyMirrored(), true);
// it could be, that parentDirInode does not exist
// in fsck we create a temporary inode for this case, so that we can modify the dentry
// hopefully, the inode itself will get fixed later
if ( unlikely(!parentDirInode) )
{
log.log(
Log_NOTICE,
"Could not reference directory. EntryID: " + parentID
+ " => using temporary directory inode ");
// create temporary inode
int mode = S_IFDIR | S_IRWXU;
UInt16Vector stripeTargets;
Raid0Pattern stripePattern(0, stripeTargets, 0);
parentDirInode = new DirInode(parentID, mode, 0, 0,
Program::getApp()->getLocalNode().getNumID(), stripePattern, getIsBuddyMirrored());
parentDirInodeIsTemp = true;
}
if ( parentDirInode->listIncremental(lastContDirOffset, remainingOutNames, &entryNames,
&newContDirOffset) == FhgfsOpsErr_SUCCESS )
{
lastContDirOffset = newContDirOffset;
}
else
{
log.log(Log_WARNING, "Could not list contents of directory. EntryID: " + parentID);
}
// actually process the entries
for ( StringListIter namesIter = entryNames.begin(); namesIter != entryNames.end();
namesIter++ )
{
std::string filename = MetaStorageTk::getMetaDirEntryPath(
getIsBuddyMirrored()
? Program::getApp()->getBuddyMirrorDentriesPath()->str()
: Program::getApp()->getDentriesPath()->str(), parentID) + "/" + *namesIter;
// create a EntryInfo and put the information into an FsckDirEntry object
EntryInfo entryInfo;
FileInodeStoreData inodeDiskData;
bool hasInlinedInode = false;
int32_t saveDevice = 0;
uint64_t saveInode = 0;
auto [getEntryRes, isFileOpen] = metaStore->getEntryData(parentDirInode, *namesIter, &entryInfo,
&inodeDiskData);
if (getEntryRes == FhgfsOpsErr_SUCCESS ||
getEntryRes == FhgfsOpsErr_DYNAMICATTRIBSOUTDATED )
{
DirEntryType entryType = entryInfo.getEntryType();
const std::string& dentryID = entryInfo.getEntryID();
const std::string& dentryName = *namesIter;
NumNodeID dentryOwnerID = entryInfo.getOwnerNodeID();
FsckDirEntryType fsckEntryType = FsckTk::DirEntryTypeToFsckDirEntryType(entryType);
// stat the file to get device and inode information
struct stat statBuf;
int statRes = stat(filename.c_str(), &statBuf);
if (likely(!statRes))
{
saveDevice = statBuf.st_dev;
saveInode = statBuf.st_ino;
}
else
{
log.log(Log_CRITICAL, "Could not stat dir entry file; entryID: " + dentryID
+ ";filename: " + filename);
}
if ( (DirEntryType_ISFILE(entryType)) && (entryInfo.getIsInlined() ) )
{
hasInlinedInode = true;
}
FsckDirEntry fsckDirEntry(dentryID, dentryName, parentID, localNodeNumID,
dentryOwnerID, fsckEntryType, hasInlinedInode, localNodeNumID,
saveDevice, saveInode, entryInfo.getIsBuddyMirrored());
dirEntriesOutgoing.push_back(fsckDirEntry);
}
else
{
log.log(Log_WARNING, "Unable to create dir entry from entry with name " + *namesIter
+ " in directory with ID " + parentID);
}
// now, if the inode data is inlined we create an fsck inode object here
if ( hasInlinedInode )
{
std::string inodeID = inodeDiskData.getEntryID();
int pathInfoFlag;
if (inodeDiskData.getOrigFeature() == FileInodeOrigFeature_TRUE)
pathInfoFlag = PATHINFO_FEATURE_ORIG;
else
pathInfoFlag = PATHINFO_FEATURE_ORIG_UNKNOWN;
unsigned origUID = inodeDiskData.getOrigUID();
std::string origParentEntryID = inodeDiskData.getOrigParentEntryID();
PathInfo pathInfo(origUID, origParentEntryID, pathInfoFlag);
unsigned userID;
unsigned groupID;
int64_t fileSize;
unsigned numHardLinks;
uint64_t numBlocks;
StatData* statData;
StatData updatedStatData;
if (getEntryRes == FhgfsOpsErr_SUCCESS)
statData = inodeDiskData.getInodeStatData();
else
{
FhgfsOpsErr statRes = MsgHelperStat::stat(&entryInfo, true, getMsgHeaderUserID(),
updatedStatData);
if (statRes == FhgfsOpsErr_SUCCESS)
statData = &updatedStatData;
else
statData = NULL;
}
if ( statData )
{
userID = statData->getUserID();
groupID = statData->getGroupID();
fileSize = statData->getFileSize();
numHardLinks = statData->getNumHardlinks();
numBlocks = statData->getNumBlocks();
}
else
{
log.logErr(std::string("Unable to get stat data of inlined file inode: ") + inodeID
+ ". SysErr: " + System::getErrString());
userID = 0;
groupID = 0;
fileSize = 0;
numHardLinks = 0;
numBlocks = 0;
}
UInt16Vector stripeTargets;
unsigned chunkSize;
FsckStripePatternType stripePatternType = FsckTk::stripePatternToFsckStripePattern(
inodeDiskData.getPattern(), &chunkSize, &stripeTargets);
FsckFileInode fileInode(inodeID, parentID, localNodeNumID, pathInfo, userID, groupID,
fileSize, numHardLinks, numBlocks, stripeTargets, stripePatternType, chunkSize,
localNodeNumID, saveInode, saveDevice, true, entryInfo.getIsBuddyMirrored(),
true, inodeDiskData.getIsBuddyMirrored() != getIsBuddyMirrored());
inlinedFileInodesOutgoing.push_back(fileInode);
}
}
if ( parentDirInodeIsTemp )
SAFE_DELETE(parentDirInode);
else
metaStore->releaseDir(parentID);
if ( entryNames.size() < remainingOutNames )
{
// directory is at the end => proceed with next
hasNext = StorageTkEx::getNextContDirID(hashDirNum, getIsBuddyMirrored(),
lastHashDirOffset, &currentContDirID, &newHashDirOffset);
if ( hasNext )
{
lastHashDirOffset = newHashDirOffset;
lastContDirOffset = 0;
readOutEntries += entryNames.size();
// we found a new .cont directory => send it to fsck
FsckContDir contDir(currentContDirID, localNodeNumID, getIsBuddyMirrored());
contDirsOutgoing.push_back(contDir);
}
}
else
{
// there are more to come, but we need to exit the loop now, because maxCount is reached
hasNext = false;
}
}
ctx.sendResponse(
RetrieveDirEntriesRespMsg(&contDirsOutgoing, &dirEntriesOutgoing,
&inlinedFileInodesOutgoing, currentContDirID, lastHashDirOffset, lastContDirOffset) );
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/fsck/RetrieveDirEntriesMsg.h>
#include <common/net/message/fsck/RetrieveDirEntriesRespMsg.h>
class RetrieveDirEntriesMsgEx : public RetrieveDirEntriesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,166 @@
#include "RetrieveFsIDsMsgEx.h"
#include <common/storage/striping/Raid0Pattern.h>
#include <common/threading/SafeRWLock.h>
#include <program/Program.h>
bool RetrieveFsIDsMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("Incoming RetrieveFsIDsMsg");
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
unsigned hashDirNum = getHashDirNum();
bool buddyMirrored = getBuddyMirrored();
std::string currentContDirID = getCurrentContDirID();
unsigned maxOutIDs = getMaxOutIDs();
int64_t lastContDirOffset = getLastContDirOffset();
int64_t lastHashDirOffset = getLastHashDirOffset();
int64_t newHashDirOffset;
FsckFsIDList fsIDsOutgoing;
unsigned readOutIDs = 0;
NumNodeID localNodeNumID = buddyMirrored
? NumNodeID(Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID())
: Program::getApp()->getLocalNode().getNumID();
MirrorBuddyGroupMapper* bgm = Program::getApp()->getMetaBuddyGroupMapper();
if (buddyMirrored &&
(bgm->getLocalBuddyGroup().secondTargetID == app->getLocalNode().getNumID().val()
|| bgm->getLocalGroupID() == 0))
{
ctx.sendResponse(
RetrieveFsIDsRespMsg(&fsIDsOutgoing, currentContDirID, lastHashDirOffset,
lastContDirOffset));
return true;
}
bool hasNext;
if ( currentContDirID.empty() )
{
hasNext = StorageTkEx::getNextContDirID(hashDirNum, buddyMirrored, lastHashDirOffset,
&currentContDirID, &newHashDirOffset);
if ( hasNext )
lastHashDirOffset = newHashDirOffset;
}
else
hasNext = true;
while ( hasNext )
{
std::string parentID = currentContDirID;
std::string idPath = MetaStorageTk::getMetaDirEntryIDPath(
MetaStorageTk::getMetaDirEntryPath(
buddyMirrored
? app->getBuddyMirrorDentriesPath()->str()
: app->getDentriesPath()->str(),
parentID));
bool parentDirInodeIsTemp = false;
StringList outNames;
int64_t outNewServerOffset;
ListIncExOutArgs outArgs(&outNames, NULL, NULL, NULL, &outNewServerOffset);
FhgfsOpsErr listRes;
unsigned remainingOutIDs = maxOutIDs - readOutIDs;
DirInode* parentDirInode = metaStore->referenceDir(parentID, buddyMirrored, true);
// it could be, that parentDirInode does not exist
// in fsck we create a temporary inode for this case, so that we can modify the dentry
// hopefully, the inode itself will get fixed later
if ( unlikely(!parentDirInode) )
{
log.log(
Log_NOTICE,
"Could not reference directory. EntryID: " + parentID
+ " => using temporary directory inode ");
// create temporary inode
int mode = S_IFDIR | S_IRWXU;
UInt16Vector stripeTargets;
Raid0Pattern stripePattern(0, stripeTargets, 0);
parentDirInode = new DirInode(parentID, mode, 0, 0,
Program::getApp()->getLocalNode().getNumID(), stripePattern, buddyMirrored);
parentDirInodeIsTemp = true;
}
listRes = parentDirInode->listIDFilesIncremental(lastContDirOffset, 0, remainingOutIDs,
outArgs);
lastContDirOffset = outNewServerOffset;
if ( parentDirInodeIsTemp )
SAFE_DELETE(parentDirInode);
else
metaStore->releaseDir(parentID);
if (listRes != FhgfsOpsErr_SUCCESS)
{
log.logErr("Could not read dentry-by-ID files; parentID: " + parentID);
}
// process entries
readOutIDs += outNames.size();
for ( StringListIter iter = outNames.begin(); iter != outNames.end(); iter++ )
{
std::string id = *iter;
std::string filename = idPath + "/" + id;
// stat the file to get device and inode information
struct stat statBuf;
int statRes = stat(filename.c_str(), &statBuf);
int saveDevice;
uint64_t saveInode;
if ( likely(!statRes) )
{
saveDevice = statBuf.st_dev;
saveInode = statBuf.st_ino;
}
else
{
saveDevice = 0;
saveInode = 0;
log.log(Log_CRITICAL,
"Could not stat ID file; ID: " + id + ";filename: " + filename);
}
FsckFsID fsID(id, parentID, localNodeNumID, saveDevice, saveInode, buddyMirrored);
fsIDsOutgoing.push_back(fsID);
}
if ( readOutIDs < maxOutIDs )
{
// directory is at the end => proceed with next
hasNext = StorageTkEx::getNextContDirID(hashDirNum, buddyMirrored, lastHashDirOffset,
&currentContDirID, &newHashDirOffset);
if ( hasNext )
{
lastHashDirOffset = newHashDirOffset;
lastContDirOffset = 0;
}
}
else
{
// there are more to come, but we need to exit the loop now, because maxCount is reached
hasNext = false;
}
}
ctx.sendResponse(
RetrieveFsIDsRespMsg(&fsIDsOutgoing, currentContDirID, lastHashDirOffset,
lastContDirOffset) );
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/fsck/RetrieveFsIDsMsg.h>
#include <common/net/message/fsck/RetrieveFsIDsRespMsg.h>
class RetrieveFsIDsMsgEx : public RetrieveFsIDsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,25 @@
#include "RetrieveInodesMsgEx.h"
#include <program/Program.h>
bool RetrieveInodesMsgEx::processIncoming(ResponseContext& ctx)
{
LogContext log("Incoming RetrieveInodesMsg");
MetaStore *metaStore = Program::getApp()->getMetaStore();
unsigned hashDirNum = getHashDirNum();
unsigned maxOutInodes = getMaxOutInodes();
int64_t lastOffset = getLastOffset();
int64_t newOffset;
FsckFileInodeList fileInodesOutgoing;
FsckDirInodeList dirInodesOutgoing;
metaStore->getAllInodesIncremental(hashDirNum, lastOffset, maxOutInodes, &dirInodesOutgoing,
&fileInodesOutgoing, &newOffset, getIsBuddyMirrored());
ctx.sendResponse(RetrieveInodesRespMsg(&fileInodesOutgoing, &dirInodesOutgoing, newOffset) );
return true;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <common/net/message/fsck/RetrieveInodesMsg.h>
#include <common/net/message/fsck/RetrieveInodesRespMsg.h>
class RetrieveInodesMsgEx : public RetrieveInodesMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,51 @@
#include "UpdateDirAttribsMsgEx.h"
#include <storage/MetaStore.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool UpdateDirAttribsMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "UpdateDirAttribsMsg incoming";
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
FsckDirInodeList& inodes = getInodes();
FsckDirInodeList failedInodes;
for (FsckDirInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++)
{
// call the updating method
const std::string& dirID = iter->getID();
FileIDLock lock;
if (iter->getIsBuddyMirrored())
lock = {entryLockStore, dirID, true};
DirInode* dirInode = metaStore->referenceDir(dirID, iter->getIsBuddyMirrored(), true);
if (!dirInode)
{
LogContext(logContext).logErr("Unable to reference directory; ID: " + dirID);
failedInodes.push_back(*iter);
continue;
}
FhgfsOpsErr refreshRes = dirInode->refreshMetaInfo();
metaStore->releaseDir(dirID);
if (refreshRes != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).log(Log_WARNING, "Failed to update attributes of directory. "
"entryID: " + dirID);
failedInodes.push_back(*iter);
}
}
ctx.sendResponse(UpdateDirAttribsRespMsg(&failedInodes) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/UpdateDirAttribsMsg.h>
#include <common/net/message/fsck/UpdateDirAttribsRespMsg.h>
class UpdateDirAttribsMsgEx : public UpdateDirAttribsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};

View File

@@ -0,0 +1,62 @@
#include "UpdateFileAttribsMsgEx.h"
#include <net/msghelpers/MsgHelperStat.h>
#include <program/Program.h>
#include <toolkit/BuddyCommTk.h>
bool UpdateFileAttribsMsgEx::processIncoming(ResponseContext& ctx)
{
const char* logContext = "UpdateFileAttribsMsg incoming";
MetaStore* metaStore = Program::getApp()->getMetaStore();
EntryLockStore* entryLockStore = Program::getApp()->getMirroredSessions()->getEntryLockStore();
FsckFileInodeList& inodes = getInodes();
FsckFileInodeList failedInodes;
for (FsckFileInodeListIter iter = inodes.begin(); iter != inodes.end(); iter++)
{
// create an EntryInfo object (NOTE: dummy fileName)
EntryInfo entryInfo(iter->getSaveNodeID(), iter->getParentDirID(), iter->getID(), "",
DirEntryType_REGULARFILE,
(iter->getIsBuddyMirrored() ? ENTRYINFO_FEATURE_BUDDYMIRRORED : 0) |
(iter->getIsInlined() ? ENTRYINFO_FEATURE_INLINED : 0));
FileIDLock lock;
if (iter->getIsBuddyMirrored())
lock = {entryLockStore, entryInfo.getEntryID(), true};
auto [inode, referenceRes] = metaStore->referenceFile(&entryInfo);
if (inode)
{
inode->setNumHardlinksUnpersistent(iter->getNumHardLinks());
inode->updateInodeOnDisk(&entryInfo);
// call the dynamic attribs refresh method
FhgfsOpsErr refreshRes = MsgHelperStat::refreshDynAttribs(&entryInfo, true,
getMsgHeaderUserID() );
if (refreshRes != FhgfsOpsErr_SUCCESS)
{
LogContext(logContext).log(Log_WARNING, "Failed to update dynamic attributes of file. "
"entryID: " + iter->getID());
failedInodes.push_back(*iter);
}
/* only release it here, as refreshDynAttribs() also takes an inode reference and can
* do the reference from in-memory data then */
metaStore->releaseFile(entryInfo.getParentEntryID(), inode);
}
else
{
LogContext(logContext).log(Log_WARNING, "Could not reference inode to update attributes. "
"entryID: " + iter->getID());
failedInodes.push_back(*iter);
}
}
ctx.sendResponse(UpdateFileAttribsRespMsg(&failedInodes) );
return true;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <common/net/message/NetMessage.h>
#include <common/net/message/fsck/UpdateFileAttribsMsg.h>
#include <common/net/message/fsck/UpdateFileAttribsRespMsg.h>
class UpdateFileAttribsMsgEx : public UpdateFileAttribsMsg
{
public:
virtual bool processIncoming(ResponseContext& ctx);
};