#include #include #include #include #include #include #include #include "FLockEntryMsgEx.h" bool FLockEntryMsgEx::processIncoming(ResponseContext& ctx) { /* note: this code is very similar to FLockRangeMsgEx::processIncoming(), so if you change something here, you probably want to change it there, too. */ clientResult = FhgfsOpsErr_INTERNAL; updateNodeOp(ctx, MetaOpCounter_FLOCKENTRY); return BaseType::processIncoming(ctx); } FileIDLock FLockEntryMsgEx::lock(EntryLockStore& store) { return {&store, getEntryInfo()->getEntryID(), true}; } std::unique_ptr FLockEntryMsgEx::executeLocally(ResponseContext& ctx, bool isSecondary) { App* app = Program::getApp(); MetaStore* metaStore = app->getMetaStore(); unsigned ownerFD = SessionTk::ownerFDFromHandleID(getFileHandleID() ); EntryLockDetails lockDetails(getClientNumID(), getClientFD(), getOwnerPID(), getLockAckID(), getLockTypeFlags() ); 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_UNLOCK) { // 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->flockEntry(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->flockEntry(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::notifyWaitersEntryLock(LockEntryNotifyType_FLOCK, 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, "", getClientNumID(), clientResult); return boost::make_unique(clientResult); } void FLockEntryMsgEx::forwardToSecondary(ResponseContext& ctx) { sendToSecondary(ctx, *this, NETMSGTYPE_FLockEntryResp, clientResult); }