beegfs/meta/source/net/message/session/locking/FLockRangeMsgEx.cpp
2025-08-10 01:34:16 +02:00

135 lines
4.3 KiB
C++

#include <common/net/message/session/locking/FLockRangeRespMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <common/toolkit/SessionTk.h>
#include <net/msghelpers/MsgHelperLocking.h>
#include <program/Program.h>
#include <session/SessionStore.h>
#include <storage/MetaStore.h>
#include "FLockRangeMsgEx.h"
bool FLockRangeMsgEx::processIncoming(ResponseContext& ctx)
{
/* note: this code is very similar to FLockEntryMsgEx::processIncoming(), so if you change
something here, you probably want to change it there, too. */
clientResult = FhgfsOpsErr_INTERNAL;
updateNodeOp(ctx, MetaOpCounter_FLOCKRANGE);
return BaseType::processIncoming(ctx);
}
FileIDLock FLockRangeMsgEx::lock(EntryLockStore& store)
{
return {&store, getEntryInfo()->getEntryID(), true};
}
std::unique_ptr<MirroredMessageResponseState> FLockRangeMsgEx::executeLocally(ResponseContext& ctx,
bool isSecondary)
{
App* app = Program::getApp();
MetaStore* metaStore = app->getMetaStore();
unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() );
RangeLockDetails lockDetails(getClientNumID(), getOwnerPID(), getLockAckID(),
getLockTypeFlags(), getStart(), getEnd() );
LOG_DBG(GENERAL, SPAM, lockDetails.toString());
EntryInfo* entryInfo = getEntryInfo();
SessionStore* sessions = entryInfo->getIsBuddyMirrored()
? app->getMirroredSessions()
: app->getSessions();
// find sessionFile
Session* session = sessions->referenceSession(getClientNumID(), true);
SessionFileStore* sessionFiles = session->getFiles();
SessionFile* sessionFile = sessionFiles->referenceSession(ownerFD);
if(!sessionFile)
{ // sessionFile not exists (mds restarted?)
// check if this is just an UNLOCK REQUEST
if(getLockTypeFlags() & ENTRYLOCKTYPE_LOCKOPS_REMOVE)
{ // it's an unlock => we'll just ignore it (since the locks are gone anyways)
clientResult = FhgfsOpsErr_SUCCESS;
goto cleanup_session;
}
// check if this is a LOCK CANCEL REQUEST
if(getLockTypeFlags() & ENTRYLOCKTYPE_CANCEL)
{ // it's a lock cancel
/* this is an important special case, because client might have succeeded in closing the
file but the conn might have been interrupted during unlock, so we definitely have to try
canceling the lock here */
// if the file still exists, just do the lock cancel without session recovery attempt
auto [lockCancelFile, referenceRes] = metaStore->referenceFile(entryInfo);
if(lockCancelFile)
{
lockCancelFile->flockRange(lockDetails);
metaStore->releaseFile(entryInfo->getParentEntryID(), lockCancelFile);
}
clientResult = FhgfsOpsErr_SUCCESS;
goto cleanup_session;
}
// it's a LOCK REQUEST => try to recover session file to do the locking
clientResult = MsgHelperLocking::trySesssionRecovery(entryInfo, getClientNumID(),
ownerFD, sessionFiles, &sessionFile);
// (note: sessionFile==NULL now if recovery was not successful)
} // end of session file session recovery attempt
if(sessionFile)
{ // sessionFile exists (or was successfully recovered)
auto& file = sessionFile->getInode();
auto lockGranted = file->flockRange(lockDetails);
if (!lockGranted.first)
clientResult = FhgfsOpsErr_WOULDBLOCK;
else
clientResult = FhgfsOpsErr_SUCCESS;
if ((getLockTypeFlags() & ENTRYLOCKTYPE_UNLOCK) && !file->incrementFileVersion(entryInfo))
{
LOG(GENERAL, ERR, "Could not bump file version.", file->getEntryID());
sessionFiles->releaseSession(sessionFile, entryInfo);
clientResult = FhgfsOpsErr_INTERNAL;
goto cleanup_session;
}
if (!lockGranted.second.empty() && !isSecondary)
LockingNotifier::notifyWaitersRangeLock(file->getReferenceParentID(), file->getEntryID(),
file->getIsBuddyMirrored(), std::move(lockGranted.second));
// cleanup
sessionFiles->releaseSession(sessionFile, entryInfo);
}
// cleanup
cleanup_session:
sessions->releaseSession(session);
LOG_DBG(GENERAL, SPAM, "", clientResult);
return boost::make_unique<ResponseState>(clientResult);
}
void FLockRangeMsgEx::forwardToSecondary(ResponseContext& ctx)
{
sendToSecondary(ctx, *this, NETMSGTYPE_FLockRangeResp, clientResult);
}