beegfs/meta/source/net/msghelpers/MsgHelperOpen.cpp
2025-08-10 01:34:16 +02:00

98 lines
3.6 KiB
C++

#include <common/toolkit/MathTk.h>
#include <common/toolkit/MessagingTk.h>
#include <common/toolkit/SessionTk.h>
#include <common/storage/striping/Raid0Pattern.h>
#include <net/msghelpers/MsgHelperTrunc.h>
#include <program/Program.h>
#include <storage/MetaStore.h>
#include "MsgHelperOpen.h"
/**
* Note: This only does the basic open; you probably still want to create the session for this
* opened file afterwards.
* Note: Also performs truncation based on accessFlags if necessary.
*
* @param msgUserID only used for msg header info.
* @param outOpenFile only set if return indicates success.
*/
FhgfsOpsErr MsgHelperOpen::openFile(EntryInfo* entryInfo, unsigned accessFlags,
bool useQuota, bool bypassAccessCheck, unsigned msgUserID, MetaFileHandle& outFileInode,
bool isSecondary)
{
const char* logContext = "Open File Helper";
IGNORE_UNUSED_VARIABLE(logContext);
bool truncLocalRequired = false;
if(accessFlags & OPENFILE_ACCESS_TRUNC)
truncLocalRequired = MsgHelperTrunc::isTruncChunkRequired(entryInfo, 0);
FhgfsOpsErr openRes = openMetaFile(entryInfo, accessFlags, bypassAccessCheck, outFileInode);
if(openRes != FhgfsOpsErr_SUCCESS)
return openRes;
/* check chunkSize for compatibility.
this check was introduced in 2011.05-r6, when we switched from arbitrary chunk sizes to the
new chunk size constraints (min size and power of two). the check can be removed in a future
release, when we are sure that there are no old installations with arbitrary chunk sizes
left. */
unsigned chunkSize = outFileInode->getStripePattern()->getChunkSize();
if(unlikely( (chunkSize < STRIPEPATTERN_MIN_CHUNKSIZE) ||
!MathTk::isPowerOfTwo(chunkSize) ) )
{ // validity check failed => don't open this file (we would risk corrupting it otherwise)
LogContext(logContext).logErr("This version of BeeGFS is not compatible with this "
"chunk size: " + StringTk::uintToStr(chunkSize) + ". "
"Refusing to open file. "
"parentInfo: " + entryInfo->getParentEntryID() + " "
"entryInfo: " + entryInfo->getEntryID() );
openMetaFileCompensate(entryInfo, std::move(outFileInode), accessFlags);
return FhgfsOpsErr_INTERNAL;
}
if(truncLocalRequired && !isSecondary)
{ // trunc was specified and is needed => do it
LOG_DEBUG(logContext, Log_DEBUG, std::string("Opening with trunc local") );
DynamicFileAttribsVec dynAttribs;
FhgfsOpsErr truncRes = MsgHelperTrunc::truncChunkFile(
*outFileInode, entryInfo, 0, useQuota, msgUserID, dynAttribs);
if(unlikely(truncRes != FhgfsOpsErr_SUCCESS) )
{ // error => undo open()
openMetaFileCompensate(entryInfo, std::move(outFileInode), accessFlags);
openRes = truncRes;
}
}
return openRes;
}
FhgfsOpsErr MsgHelperOpen::openMetaFile(EntryInfo* entryInfo, unsigned accessFlags,
bool bypassAccessCheck, MetaFileHandle& outOpenInode)
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
FhgfsOpsErr openRes = metaStore->openFile(entryInfo, accessFlags, bypassAccessCheck, outOpenInode);
return openRes;
}
/**
* Undo an open.
* (Typically called when an error occurred after a successful open).
*/
void MsgHelperOpen::openMetaFileCompensate(EntryInfo* entryInfo,
MetaFileHandle inode, unsigned accessFlags)
{
MetaStore* metaStore = Program::getApp()->getMetaStore();
unsigned numHardlinks; // ignored here
unsigned numInodeRefs; // ignored here
bool lastWriterClosed; // ignored here
metaStore->closeFile(entryInfo, std::move(inode), accessFlags, &numHardlinks, &numInodeRefs,
lastWriterClosed);
}