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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,146 @@
#ifndef FHGFSOPSCOMMKIT_H_
#define FHGFSOPSCOMMKIT_H_
#include <common/storage/PathInfo.h>
#ifdef BEEGFS_NVFS
#include <common/storage/RdmaInfo.h>
#endif
#include <os/iov_iter.h>
#include "FhgfsOpsCommKitCommon.h"
struct FileOpState;
typedef struct FileOpState FileOpState;
struct FsyncContext;
bool FhgfsOpsCommKit_initEmergencyPools(void);
void FhgfsOpsCommKit_releaseEmergencyPools(void);
extern void FhgfsOpsCommkit_communicate(App* app, RemotingIOInfo* ioInfo,
struct list_head* targetInfos, const struct CommKitContextOps* ops, void* private);
extern void FhgfsOpsCommKit_readfileV2bCommunicate(App* app, RemotingIOInfo* ioInfo,
struct list_head* states, void (*nextIter)(CommKitContext*, FileOpState*),
void (*prepare)(CommKitContext*, FileOpState*));
extern void FhgfsOpsCommKit_writefileV2bCommunicate(App* app, RemotingIOInfo* ioInfo,
struct list_head* states, void (*nextIter)(CommKitContext*, FileOpState*),
void (*prepare)(CommKitContext*, FileOpState*));
extern void FhgfsOpsCommKit_fsyncCommunicate(App* app, RemotingIOInfo* ioInfo,
struct FsyncContext* context);
extern void FhgfsOpsCommKit_statStorageCommunicate(App* app, struct list_head* targets);
extern void FhgfsOpsCommKit_initFileOpState(FileOpState* state, loff_t offset, size_t size,
uint16_t targetID);
enum CommKitState
{
CommKitState_PREPARE,
CommKitState_SENDHEADER,
CommKitState_SENDDATA,
CommKitState_RECVHEADER,
CommKitState_RECVDATA,
CommKitState_SOCKETINVALIDATE,
CommKitState_CLEANUP,
CommKitState_RETRYWAIT,
CommKitState_DONE,
};
struct CommKitTargetInfo
{
struct list_head targetInfoList;
// (set to _PREPARE in the beginning, assigned by the state-creator)
enum CommKitState state; // the current stage of the individual communication process
// used by GenericResponse handler
struct {
unsigned peerTryAgain:1;
unsigned indirectCommError:1;
unsigned indirectCommErrorNoRetry:1;
} logged;
// assigned by the state-creator
char* headerBuffer; // for serialization
uint16_t targetID;
uint16_t selectedTargetID; // either targetID or the buddy, if useBuddyMirrorSecond
bool useBuddyMirrorSecond; // if buddy mirroring, this msg goes to secondary
// set by _PREPARE handler
Node* node; // target-node reference
Socket* socket; // target-node connection
unsigned headerSize;
// error if negative, other set by specialized actions
int64_t nodeResult;
};
struct FileOpState
{
struct CommKitTargetInfo base;
// data for spefic modes (will be assigned by the corresponding modes)
size_t transmitted; // how much data has been transmitted already
size_t toBeTransmitted; // how much data has to be transmitted
size_t totalSize; // how much data was requested
// data for all modes
// (assigned by the state-creator)
struct iov_iter data;
loff_t offset; // target-node local offset
bool firstWriteDoneForTarget; /* true if a chunk was previously written to this target in
this session; used for the session check */
bool receiveFileData; /* if false, receive the int64 fragment length, else the fragment */
// result data
int64_t expectedNodeResult; // the amount of data that we wanted to read
#ifdef BEEGFS_NVFS
RdmaInfo* rdmap;
#endif
};
struct FsyncContext {
unsigned userID;
bool forceRemoteFlush;
bool checkSession;
bool doSyncOnClose;
struct list_head states;
};
struct FsyncState {
struct CommKitTargetInfo base;
bool firstWriteDoneForTarget;
};
extern void FhgfsOpsCommKit_initFsyncState(struct FsyncContext* context, struct FsyncState* state,
uint16_t targetID);
struct StatStorageState
{
struct CommKitTargetInfo base;
int64_t totalSize;
int64_t totalFree;
};
extern void FhgfsOpsCommKit_initStatStorageState(struct list_head* states,
struct StatStorageState* state, uint16_t targetID);
#endif /*FHGFSOPSCOMMKIT_H_*/

View File

@@ -0,0 +1,187 @@
#ifndef FHGFSOPSCOMMKITCOMMON_H_
#define FHGFSOPSCOMMKITCOMMON_H_
#include <app/log/Logger.h>
#include <common/net/message/session/rw/WriteLocalFileRespMsg.h>
#include <common/toolkit/MessagingTk.h>
#include <common/toolkit/SocketTk.h>
#include <common/Common.h>
#include <common/Types.h>
#include <net/filesystem/RemotingIOInfo.h>
#include <nodes/NodeStoreEx.h>
#define BEEGFS_COMMKIT_MSGBUF_SIZE 4096
#define COMMKIT_DEBUG_READ_SEND (1 << 0)
#define COMMKIT_DEBUG_READ_HEADER (1 << 1)
#define COMMKIT_DEBUG_RECV_DATA (1 << 2)
#define COMMKIT_DEBUG_WRITE_HEADER (1 << 3)
#define COMMKIT_DEBUG_WRITE_POLL (1 << 4)
#define COMMKIT_DEBUG_WRITE_SEND (1 << 5)
#define COMMKIT_DEBUG_WRITE_RECV (1 << 6)
// #define BEEGFS_COMMKIT_DEBUG 0b010
#ifndef BEEGFS_COMMKIT_DEBUG
#define BEEGFS_COMMKIT_DEBUG 0
#endif
#ifdef BEEGFS_COMMKIT_DEBUG
#define CommKitErrorInjectRate 101 // fail a send/receive req every X jiffies
#endif
struct CommKitContext;
typedef struct CommKitContext CommKitContext;
static inline void __FhgfsOpsCommKitCommon_pollStateSocks(CommKitContext* context,
size_t numStates);
static inline void __FhgfsOpsCommKitCommon_handlePollError(CommKitContext* context,
int pollRes);
struct CommKitTargetInfo;
enum
{
CK_RETRY_BUDDY_FALLBACK = 1 << 0,
CK_RETRY_LOOP_EAGAIN = 1 << 1,
};
enum CKTargetBadAction
{
CK_SKIP_TARGET = 0,
CK_CONTINUE_TARGET = 1,
};
struct CommKitContextOps
{
enum CKTargetBadAction (*selectedTargetBad)(CommKitContext*, struct CommKitTargetInfo*,
const CombinedTargetState*);
unsigned (*prepareHeader)(CommKitContext*, struct CommKitTargetInfo*);
// returns >0 for successful send, 0 to advance to next state, or negative error code
int (*sendData)(CommKitContext*, struct CommKitTargetInfo*);
// return >= for success, 0 to advance, or negative beegfs error code
int (*recvHeader)(CommKitContext*, struct CommKitTargetInfo*);
// return >= for success, 0 to advance, or negative beegfs error code
int (*recvData)(CommKitContext*, struct CommKitTargetInfo*);
void (*printSendDataDetails)(CommKitContext*, struct CommKitTargetInfo*);
void (*printSocketDetails)(CommKitContext*, struct CommKitTargetInfo*);
int retryFlags;
const char* logContext;
};
/**
* Additional data that is required or useful for all the states.
* (This is shared states data.)
*
* invariant: (numRetryWaiters + numDone + numUnconnectable + numPollSocks) <= numStates
*/
struct CommKitContext
{
const struct CommKitContextOps* ops;
App* app;
Logger* log;
void* private;
RemotingIOInfo* ioInfo;
struct list_head* targetInfoList;
unsigned numRetryWaiters; // number of states with a communication error
unsigned numDone; // number of finished states
unsigned numAcquiredConns; // number of acquired conns to decide waiting or not (avoids deadlock)
unsigned numUnconnectable; // states that didn't get a conn this round (reset to 0 in each round)
unsigned numBufferless; // states that couldn't acquire a header buffer
bool pollTimedOut;
bool pollTimeoutLogged;
bool connFailedLogged;
PollState pollState;
unsigned numPollSocks;
unsigned currentRetryNum; // number of used up retries (in case of comm errors)
unsigned maxNumRetries; // 0 if infinite number of retries enabled
#ifdef BEEGFS_NVFS
int gpudRc;
#endif
};
/**
* Poll the state socks that need to be polled.
* This will call _handlePollError() if something goes wrong with the poll(), e.g. timeout.
*
* Note: Caller must have checked that there actually are socks that need polling
* (context.numPollSocks>0) before calling this.
*/
void __FhgfsOpsCommKitCommon_pollStateSocks(CommKitContext* context, size_t numStates)
{
int pollRes;
Config* cfg = App_getConfig(context->app);
size_t numWaiters = context->numPollSocks + context->numRetryWaiters +
context->numDone + context->numUnconnectable + context->numBufferless;
/* if not all the states are polling or done, some states must be ready to do something
immediately => set timeout to 0 (non-blocking) */
/* note: be very careful with timeoutMS==0, because that means we don't release the CPU,
so we need to ensure that timeoutMS==0 is no permanent condition. */
int timeoutMS = (numWaiters < numStates) ? 0 : cfg->connMsgLongTimeout;
BEEGFS_BUG_ON_DEBUG(numWaiters > numStates, "numWaiters > numStates should never happen");
pollRes = SocketTk_poll(&context->pollState, timeoutMS);
if(unlikely( (timeoutMS && pollRes <= 0) || (pollRes < 0) ) )
__FhgfsOpsCommKitCommon_handlePollError(context, pollRes);
}
void __FhgfsOpsCommKitCommon_handlePollError(CommKitContext* context, int pollRes)
{
// note: notifies the waiting sockets via context.pollTimedOut (they do not care whether
// it was a timeout or an error)
if(!context->pollTimeoutLogged)
{
if(!pollRes)
{ // no incoming data => timout or interrupted
if (fatal_signal_pending(current))
{ // interrupted
Logger_logFormatted(context->log, 3, context->ops->logContext,
"Communication (poll() ) interrupted by signal.");
}
else
{ // timout
Logger_logErrFormatted(context->log, context->ops->logContext,
"Communication (poll() ) timeout for %u sockets.", context->numPollSocks);
}
}
else
{ // error
Logger_logErrFormatted(context->log, context->ops->logContext,
"Communication (poll() ) error for %u sockets. ErrCode: %d",
context->numPollSocks, pollRes);
}
}
context->pollTimeoutLogged = true;
context->pollTimedOut = true;
}
#endif /*FHGFSOPSCOMMKITCOMMON_H_*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
#ifndef FHGFSOPSCOMMKITVEC_H_
#define FHGFSOPSCOMMKITVEC_H_
#include <net/filesystem/FhgfsOpsRemoting.h>
#include <toolkit/FhgfsPage.h>
#include <toolkit/FhgfsChunkPageVec.h>
#include <linux/fs.h>
#include "FhgfsOpsCommKitCommon.h"
#include "RemotingIOInfo.h"
struct FhgfsCommKitVec;
typedef struct FhgfsCommKitVec FhgfsCommKitVec;
struct CommKitVecHelper;
typedef struct CommKitVecHelper CommKitVecHelper;
extern int64_t FhgfsOpsCommKitVec_rwFileCommunicate(App* app, RemotingIOInfo* ioInfo,
FhgfsCommKitVec* comm, Fhgfs_RWType rwType);
static inline FhgfsCommKitVec FhgfsOpsCommKitVec_assignRWfileState(FhgfsChunkPageVec* pageVec,
unsigned pageIdx, unsigned numPages, loff_t offset, uint16_t targetID, char* msgBuf);
static inline void FhgfsOpsCommKitVec_setRWFileStateFirstWriteDone(
bool firstWriteDoneForTarget, FhgfsCommKitVec* outComm);
static inline size_t FhgfsOpsCommKitVec_getRemainingDataSize(FhgfsCommKitVec* comm);
static inline loff_t FhgfsOpsCommKitVec_getOffset(FhgfsCommKitVec* comm);
struct FhgfsCommKitVec
{
// Depending if we are going to read or write, the corresponding struct will be used
union
{
// NOTE: The *initial* stage for read and write MUST be RW_FILE_STAGE_PREPARE
struct readState
{
size_t reqLen; // requested size from client to server
size_t serverSize; // how many data the server is going to send (<= reqLen)
} read ;
struct writeState
{
WriteLocalFileRespMsg respMsg; // response message
} write;
};
size_t hdrLen; // size (length) of the header message
size_t numSuccessPages; // number of pages successfully handled
// data for all stages
// (assigned by the state-creator)
FhgfsChunkPageVec* pageVec;
loff_t initialOffset; // initial offset before sending any data
uint16_t targetID; // target ID
char* msgBuf; // for serialization
bool firstWriteDoneForTarget; /* true if data was previously written to this target in
this session; used for the session check */
bool useBuddyMirrorSecond; // for buddy mirroring, this msg goes to secondary
bool useServersideMirroring; // data shall be forwarded to mirror by primary
// (assigned by the preparation stage)
Node* node; // target-node reference
Socket* sock; // target-node connection
// result information
int64_t nodeResult; /* the amount of data that have been read/written on the server side
* (or a negative fhgfs error code) */
bool doHeader; // continue with the read/write header stage
};
/**
* Additional data that is required or useful for all the states.
* (This is shared states data.)
*
* invariant: (numRetryWaiters + isDone + numUnconnectable + numPollSocks) <= numStates
*/
struct CommKitVecHelper
{
App* app;
Logger* log;
char* logContext;
RemotingIOInfo* ioInfo;
};
/**
* Note: Caller still MUST initialize type.{read/write}.stage = RW_FILE_STAGE_PREPARE.
* Note: Initializes the expectedNodeResult attribute from the size argument.
* Note: Defaults to server-side mirroring.
*/
FhgfsCommKitVec FhgfsOpsCommKitVec_assignRWfileState(FhgfsChunkPageVec* pageVec,
unsigned pageIdx, unsigned numPages, loff_t offset, uint16_t targetID, char* msgBuf)
{
FhgfsCommKitVec state =
{
.initialOffset = offset,
.targetID = targetID,
.msgBuf = msgBuf,
.firstWriteDoneForTarget = false, // set via separate setter method
.useBuddyMirrorSecond = false, // set via separate setter method
.useServersideMirroring = true, // set via separate setter method
.nodeResult = -FhgfsOpsErr_INTERNAL,
.numSuccessPages = 0,
};
state.pageVec = pageVec;
return state;
}
void FhgfsOpsCommKitVec_setRWFileStateFirstWriteDone(bool firstWriteDoneForTarget,
FhgfsCommKitVec* outComm)
{
outComm->firstWriteDoneForTarget = firstWriteDoneForTarget;
}
/**
* Get the overall remaining data size (chunkPageVec + last incompletely processed page)
*/
size_t FhgfsOpsCommKitVec_getRemainingDataSize(FhgfsCommKitVec* comm)
{
return FhgfsChunkPageVec_getRemainingDataSize(comm->pageVec);
}
/**
* Get the current offset
*/
loff_t FhgfsOpsCommKitVec_getOffset(FhgfsCommKitVec* comm)
{
FhgfsChunkPageVec* pageVec = comm->pageVec;
// data size already send/received (written/read)
size_t processedSize =
FhgfsChunkPageVec_getDataSize(pageVec) - FhgfsOpsCommKitVec_getRemainingDataSize(comm);
return comm->initialOffset + processedSize;
}
#endif /*FHGFSOPSCOMMKITVEC_H_*/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,174 @@
#ifndef FHGFSOPSREMOTING_H_
#define FHGFSOPSREMOTING_H_
#include <common/Common.h>
#include <filesystem/FsObjectInfo.h>
#include <filesystem/FsDirInfo.h>
#include <filesystem/FsFileInfo.h>
#include <common/storage/StorageDefinitions.h>
#include <common/toolkit/MetadataTk.h>
#include <common/storage/FileEvent.h>
#include <common/storage/StorageErrors.h>
#include <net/filesystem/FhgfsOpsCommKit.h>
#include <net/filesystem/RemotingIOInfo.h>
#include <os/iov_iter.h>
#include <toolkit/FhgfsPage.h>
#include <toolkit/FhgfsChunkPageVec.h>
enum Fhgfs_RWType;
typedef enum Fhgfs_RWType Fhgfs_RWType;
struct FileOpVecState {
FileOpState base;
struct iov_iter data;
};
union RWFileVecState {
struct FileOpVecState read;
struct FileOpState write;
};
struct StripePattern; // forward declaration
struct NetMessage; // forward declaration
extern bool FhgfsOpsRemoting_initMsgBufCache(void);
extern void FhgfsOpsRemoting_destroyMsgBufCache(void);
extern FhgfsOpsErr FhgfsOpsRemoting_listdirFromOffset(const EntryInfo* entryInfo,
FsDirInfo* dirInfo, unsigned maxOutNames);
extern FhgfsOpsErr FhgfsOpsRemoting_statRoot(App* app, fhgfs_stat* outFhgfsStat);
static inline FhgfsOpsErr FhgfsOpsRemoting_statDirect(App* app, const EntryInfo* entryInfo,
fhgfs_stat* outFhgfsStat);
extern FhgfsOpsErr FhgfsOpsRemoting_statDirect(App* app, const EntryInfo* entryInfo,
fhgfs_stat* outFhgfsStat);
extern FhgfsOpsErr FhgfsOpsRemoting_statAndGetParentInfo(App* app, const EntryInfo* entryInfo,
fhgfs_stat* outFhgfsStat, NumNodeID* outParentNodeID, char** outParentEntryID);
extern FhgfsOpsErr FhgfsOpsRemoting_setAttr(App* app, const EntryInfo* entryInfo,
SettableFileAttribs* fhgfsAttr, int validAttribs, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_mkdir(App* app, const EntryInfo* parentInfo,
struct CreateInfo* createInfo, EntryInfo* outEntryInfo);
extern FhgfsOpsErr FhgfsOpsRemoting_rmdir(App* app, const EntryInfo* parentInfo,
const char* entryName, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_mkfile(App* app, const EntryInfo* parentInfo,
struct CreateInfo* createInfo, EntryInfo* outEntryInfo);
extern FhgfsOpsErr FhgfsOpsRemoting_mkfileWithStripeHints(App* app, const EntryInfo* parentInfo,
struct CreateInfo* createInfo, unsigned numtargets, unsigned chunksize, EntryInfo* outEntryInfo);
extern FhgfsOpsErr FhgfsOpsRemoting_unlinkfile(App* app, const EntryInfo* parentInfo,
const char* entryName, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_openfile(const EntryInfo* entryInfo, RemotingIOInfo* ioInfo,
uint32_t* outVersion, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_closefile(const EntryInfo* entryInfo,
RemotingIOInfo* ioInfo, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_closefileEx(const EntryInfo* entryInfo,
RemotingIOInfo* ioInfo, bool allowRetries, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_flockAppendEx(const EntryInfo* entryInfo, RWLock* eiRLock,
App* app, const char* fileHandleID, int64_t clientFD, int ownerPID, int lockTypeFlags,
bool allowRetries);
extern FhgfsOpsErr FhgfsOpsRemoting_flockEntryEx(const EntryInfo* entryInfo, RWLock* eiRLock,
App* app, const char* fileHandleID, int64_t clientFD, int ownerPID, int lockTypeFlags,
bool allowRetries);
extern FhgfsOpsErr FhgfsOpsRemoting_flockRangeEx(const EntryInfo* entryInfo, RWLock* eiRLock,
App* app, const char* fileHandleID, int ownerPID, int lockTypeFlags, uint64_t start, uint64_t end,
bool allowRetries);
extern ssize_t FhgfsOpsRemoting_writefileVec(struct iov_iter* iter, loff_t offset,
RemotingIOInfo* ioInfo, bool serializeWrites);
static inline ssize_t FhgfsOpsRemoting_writefile(const char __user *buf, size_t size, loff_t offset,
RemotingIOInfo* ioInfo)
{
struct iov_iter *iter = STACK_ALLOC_BEEGFS_ITER_IOV(buf, size, WRITE);
return FhgfsOpsRemoting_writefileVec(iter, offset, ioInfo, false);
}
static inline ssize_t FhgfsOpsRemoting_writefile_kernel(const char *buf, size_t size, loff_t offset,
RemotingIOInfo* ioInfo)
{
struct iov_iter *iter = STACK_ALLOC_BEEGFS_ITER_KVEC(buf, size, WRITE);
return FhgfsOpsRemoting_writefileVec(iter, offset, ioInfo, false);
}
extern ssize_t FhgfsOpsRemoting_rwChunkPageVec(FhgfsChunkPageVec *pageVec, RemotingIOInfo* ioInfo,
Fhgfs_RWType rwType);
extern ssize_t FhgfsOpsRemoting_readfileVec(struct iov_iter *iter, size_t size, loff_t offset,
RemotingIOInfo* ioInfo, FhgfsInode* fhgfsInode);
static inline ssize_t FhgfsOpsRemoting_readfile_user(char __user *buf, size_t size, loff_t offset,
RemotingIOInfo* ioInfo, FhgfsInode* fhgfsInode)
{
struct iov_iter *iter = STACK_ALLOC_BEEGFS_ITER_IOV(buf, size, READ);
return FhgfsOpsRemoting_readfileVec(iter, size, offset, ioInfo, fhgfsInode);
}
static inline ssize_t FhgfsOpsRemoting_readfile_kernel(char *buf, size_t size, loff_t offset,
RemotingIOInfo* ioInfo, FhgfsInode* fhgfsInode)
{
struct iov_iter *iter = STACK_ALLOC_BEEGFS_ITER_KVEC(buf, size, READ);
return FhgfsOpsRemoting_readfileVec(iter, size, offset, ioInfo, fhgfsInode);
}
extern FhgfsOpsErr FhgfsOpsRemoting_rename(App* app, const char* oldName, unsigned oldLen,
DirEntryType entryType, const EntryInfo* fromDirInfo, const char* newName, unsigned newLen,
const EntryInfo* toDirInfo, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_truncfile(App* app, const EntryInfo* entryInfo, loff_t size,
const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_fsyncfile(RemotingIOInfo* ioInfo, bool forceRemoteFlush,
bool checkSession, bool doSyncOnClose);
extern FhgfsOpsErr FhgfsOpsRemoting_statStoragePath(App* app, bool ignoreErrors,
int64_t* outSizeTotal, int64_t* outSizeFree);
extern FhgfsOpsErr FhgfsOpsRemoting_listXAttr(App* app, const EntryInfo* entryInfo, char* value,
size_t size, ssize_t* outSize);
extern FhgfsOpsErr FhgfsOpsRemoting_getXAttr(App* app, const EntryInfo* entryInfo, const char* name,
void* value, size_t size, ssize_t* outSize);
extern FhgfsOpsErr FhgfsOpsRemoting_removeXAttr(App* app, const EntryInfo* entryInfo,
const char* name);
extern FhgfsOpsErr FhgfsOpsRemoting_setXAttr(App* app, const EntryInfo* entryInfo, const char* name,
const char* value, const size_t size, int flags);
extern FhgfsOpsErr FhgfsOpsRemoting_lookupIntent(App* app,
const LookupIntentInfoIn* inInfo, LookupIntentInfoOut* outInfo);
extern FhgfsOpsErr FhgfsOpsRemoting_hardlink(App* app, const char* fromName, unsigned fromLen,
const EntryInfo* fromInfo, const EntryInfo* fromDirInfo, const char* toName, unsigned toLen,
const EntryInfo* toDirInfo, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_refreshEntry(App* app, const EntryInfo* entryInfo);
extern FhgfsOpsErr FhgfsOpsRemoting_bumpFileVersion(App* app, const EntryInfo* entryInfo,
bool persistent, const struct FileEvent* event);
extern FhgfsOpsErr FhgfsOpsRemoting_getFileVersion(App* app, const EntryInfo* entryInfo,
uint32_t* outVersion);
FhgfsOpsErr __FhgfsOpsRemoting_flockGenericEx(struct NetMessage* requestMsg, unsigned respMsgType,
NodeOrGroup owner, bool isBuddyMirrored, App* app, const char* fileHandleID, int lockTypeFlags,
char* lockAckID, bool allowRetries, RWLock* eiRLock);
#ifdef LOG_DEBUG_MESSAGES
extern void __FhgfsOpsRemoting_logDebugIOCall(const char* logContext, size_t size, loff_t offset,
RemotingIOInfo* ioInfo, const char* rwTypeStr);
#else
#define __FhgfsOpsRemoting_logDebugIOCall(logContext, size, offset, ioInfo, rwTypeStr)
#endif // LOG_DEBUG_MESSAGES
enum Fhgfs_RWType
{
BEEGFS_RWTYPE_READ = 0, // read request
BEEGFS_RWTYPE_WRITE // write request
};
/**
* Stat a file or directory using EntryInfo.
*/
FhgfsOpsErr FhgfsOpsRemoting_statDirect(App* app, const EntryInfo* entryInfo,
fhgfs_stat* outFhgfsStat)
{
return FhgfsOpsRemoting_statAndGetParentInfo(app, entryInfo, outFhgfsStat, NULL, NULL);
}
#endif /*FHGFSOPSREMOTING_H_*/

View File

@@ -0,0 +1,144 @@
#ifndef REMOTINGIOINFO_H_
#define REMOTINGIOINFO_H_
#include <common/Common.h>
#include <common/storage/PathInfo.h>
#include <common/storage/striping/StripePattern.h>
#include <toolkit/BitStore.h>
#include <app/App.h>
struct RemotingIOInfo;
typedef struct RemotingIOInfo RemotingIOInfo;
// inliners
static inline void RemotingIOInfo_initOpen(App* app, unsigned accessFlags,
AtomicInt* pMaxUsedTargetIndex, PathInfo* pathInfo, RemotingIOInfo* outIOInfo);
static inline void RemotingIOInfo_initSpecialClose(App* app, const char* fileHandleID,
AtomicInt* maxUsedTargetIndex, unsigned accessFlags, RemotingIOInfo* outIOInfo);
static inline void RemotingIOInfo_freeVals(RemotingIOInfo* outIOInfo);
static inline size_t RemotingIOInfo_getNumPagesPerStripe(RemotingIOInfo* ioInfo);
static inline size_t RemotingIOInfo_getNumPagesPerChunk(RemotingIOInfo* ioInfo);
struct RemotingIOInfo
{
App* app;
const char* fileHandleID;
struct StripePattern* pattern;
PathInfo* pathInfo;
unsigned accessFlags; // OPENFILE_ACCESS_... flags
// pointers to fhgfsInode->fileHandles[handleType]...
bool* needsAppendLockCleanup; // (note: can be NULL in some cases, implies "false")
AtomicInt* maxUsedTargetIndex;
BitStore* firstWriteDone;
unsigned userID; // only used in storage server write message
unsigned groupID; // only used in storage server write message
#ifdef BEEGFS_NVFS
bool nvfs;
#endif
};
/**
* Prepares a RemotingIOInfo for Remoting_openfile().
*
* Note: Be careful with this. This is only useful in very special cases (e.g. stateless file IO,
* when you call FhgfsOpsRemoting_openfile() directly). Some values like userID also need to be
* set manually in these cases.
* You will typically rather go through the inode and thus use FhgfsInode_referenceHandle().
*
* @param accessFlags OPENFILE_ACCESS_... flags
* @param maxUsedTargetIndex may be NULL for open, but in case you will use the ioInfo also for
* IO, you will probably want to set it.
*/
void RemotingIOInfo_initOpen(App* app, unsigned accessFlags, AtomicInt* maxUsedTargetIndex,
PathInfo* pathInfo, RemotingIOInfo* outIOInfo)
{
outIOInfo->app = app;
outIOInfo->fileHandleID = NULL;
outIOInfo->pattern = NULL;
outIOInfo->pathInfo = pathInfo;
outIOInfo->accessFlags = accessFlags;
outIOInfo->needsAppendLockCleanup = NULL;
outIOInfo->maxUsedTargetIndex = maxUsedTargetIndex;
outIOInfo->firstWriteDone = NULL;
outIOInfo->userID = 0;
outIOInfo->groupID = 0;
#ifdef BEEGFS_NVFS
outIOInfo->nvfs = false;
#endif
}
/**
* Initialize RemotingIOInfo for close only. This is used for very special failures in
* atomic_open and lookup_open.
*/
void RemotingIOInfo_initSpecialClose(App* app, const char* fileHandleID,
AtomicInt* maxUsedTargetIndex, unsigned accessFlags, RemotingIOInfo* outIOInfo)
{
outIOInfo->app = app;
outIOInfo->fileHandleID = fileHandleID;
outIOInfo->pattern = NULL;
outIOInfo->pathInfo = NULL;
outIOInfo->accessFlags = accessFlags;
outIOInfo->needsAppendLockCleanup = NULL;
outIOInfo->maxUsedTargetIndex = maxUsedTargetIndex;
outIOInfo->firstWriteDone = NULL;
outIOInfo->userID = 0;
outIOInfo->groupID = 0;
#ifdef BEEGFS_NVFS
outIOInfo->nvfs = false;
#endif
}
/**
* Note: Be careful with this. This is only useful in very special cases (e.g. stateless file IO,
* when you called Remoting_openfile() directly). You will typically rather use the
* FhgfsInode_referenceHandle() & Co routines.
*/
void RemotingIOInfo_freeVals(RemotingIOInfo* outIOInfo)
{
SAFE_DESTRUCT(outIOInfo->pattern, StripePattern_virtualDestruct);
SAFE_KFREE(outIOInfo->fileHandleID);
if (outIOInfo->pathInfo)
PathInfo_uninit(outIOInfo->pathInfo);
}
/**
* Return the number of pages per stripe
*/
size_t RemotingIOInfo_getNumPagesPerStripe(RemotingIOInfo* ioInfo)
{
StripePattern* pattern = ioInfo->pattern;
UInt16Vec* targetIDs = pattern->getStripeTargetIDs(pattern);
size_t numStripeNodes = UInt16Vec_length(targetIDs);
return RemotingIOInfo_getNumPagesPerChunk(ioInfo) * numStripeNodes;
}
size_t RemotingIOInfo_getNumPagesPerChunk(RemotingIOInfo* ioInfo)
{
StripePattern* pattern = ioInfo->pattern;
unsigned chunkSize = StripePattern_getChunkSize(pattern);
return chunkSize / PAGE_SIZE;
}
#endif /* REMOTINGIOINFO_H_ */

View File

@@ -0,0 +1,223 @@
// control messages
#include <common/net/message/control/AckMsgEx.h>
#include <common/net/message/control/GenericResponseMsg.h>
// nodes messages
#include <common/net/message/nodes/GetNodesRespMsg.h>
#include <common/net/message/nodes/GetStatesAndBuddyGroupsRespMsg.h>
#include <common/net/message/nodes/GetTargetMappingsRespMsg.h>
#include <common/net/message/nodes/HeartbeatRequestMsgEx.h>
#include <common/net/message/nodes/HeartbeatMsgEx.h>
#include <common/net/message/nodes/MapTargetsMsgEx.h>
#include <common/net/message/nodes/RefreshTargetStatesMsgEx.h>
#include <common/net/message/nodes/RegisterNodeRespMsg.h>
#include <common/net/message/nodes/RemoveNodeMsgEx.h>
#include <common/net/message/nodes/RemoveNodeRespMsg.h>
#include <common/net/message/nodes/SetMirrorBuddyGroupMsgEx.h>
// storage messages
#include <common/net/message/storage/creating/MkDirRespMsg.h>
#include <common/net/message/storage/creating/MkFileRespMsg.h>
#include <common/net/message/storage/creating/RmDirRespMsg.h>
#include <common/net/message/storage/creating/HardlinkRespMsg.h>
#include <common/net/message/storage/creating/UnlinkFileRespMsg.h>
#include <common/net/message/storage/listing/ListDirFromOffsetRespMsg.h>
#include <common/net/message/storage/attribs/ListXAttrRespMsg.h>
#include <common/net/message/storage/attribs/GetXAttrRespMsg.h>
#include <common/net/message/storage/attribs/RemoveXAttrRespMsg.h>
#include <common/net/message/storage/attribs/SetXAttrRespMsg.h>
#include <common/net/message/storage/attribs/RefreshEntryInfoRespMsg.h>
#include <common/net/message/storage/moving/RenameRespMsg.h>
#include <common/net/message/storage/lookup/LookupIntentRespMsg.h>
#include <common/net/message/storage/attribs/SetAttrRespMsg.h>
#include <common/net/message/storage/attribs/StatRespMsg.h>
#include <common/net/message/storage/StatStoragePathRespMsg.h>
#include <common/net/message/storage/TruncFileRespMsg.h>
// session messages
#include <common/net/message/session/opening/OpenFileRespMsg.h>
#include <common/net/message/session/opening/CloseFileRespMsg.h>
#include <common/net/message/session/rw/WriteLocalFileRespMsg.h>
#ifdef BEEGFS_NVFS
#include <common/net/message/session/rw/WriteLocalFileRDMARespMsg.h>
#endif
#include <common/net/message/session/BumpFileVersionResp.h>
#include <common/net/message/session/FSyncLocalFileRespMsg.h>
#include <common/net/message/session/GetFileVersionRespMsg.h>
#include <common/net/message/session/locking/FLockAppendRespMsg.h>
#include <common/net/message/session/locking/FLockEntryRespMsg.h>
#include <common/net/message/session/locking/FLockRangeRespMsg.h>
#include <common/net/message/session/locking/LockGrantedMsgEx.h>
#include <common/net/message/SimpleMsg.h>
#include "NetMessageFactory.h"
static bool __NetMessageFactory_deserializeRaw(App* app, DeserializeCtx* ctx,
NetMessageHeader* header, NetMessage* outMsg)
{
bool checkCompatRes;
bool deserPayloadRes;
outMsg->msgHeader = *header;
checkCompatRes = NetMessage_checkHeaderFeatureFlagsCompat(outMsg);
if(unlikely(!checkCompatRes) )
{ // incompatible feature flag was set => log error with msg type
printk_fhgfs(KERN_NOTICE,
"Received a message with incompatible feature flags. Message type: %hu; Flags (hex): %X",
header->msgType, NetMessage_getMsgHeaderFeatureFlags(outMsg) );
_NetMessage_setMsgType(outMsg, NETMSGTYPE_Invalid);
return false;
}
// deserialize message payload
deserPayloadRes = outMsg->ops->deserializePayload(outMsg, ctx);
if(unlikely(!deserPayloadRes) )
{
printk_fhgfs_debug(KERN_NOTICE, "Failed to decode message. Message type: %hu",
header->msgType);
_NetMessage_setMsgType(outMsg, NETMSGTYPE_Invalid);
return false;
}
return true;
}
/**
* The standard way to create message objects from serialized message buffers.
*
* @return NetMessage which must be deleted by the caller
* (msg->msgType is NETMSGTYPE_Invalid on error)
*/
NetMessage* NetMessageFactory_createFromBuf(App* app, char* recvBuf, size_t bufLen)
{
NetMessageHeader header;
NetMessage* msg;
DeserializeCtx ctx = {
.data = recvBuf,
.length = bufLen,
};
// decode the message header
__NetMessage_deserializeHeader(&ctx, &header);
// create the message object for the given message type
msg = NetMessageFactory_createFromMsgType(header.msgType);
if(unlikely(NetMessage_getMsgType(msg) == NETMSGTYPE_Invalid) )
{
printk_fhgfs_debug(KERN_NOTICE,
"Received an invalid or unhandled message. "
"Message type (from raw header): %hu", header.msgType);
return msg;
}
__NetMessageFactory_deserializeRaw(app, &ctx, &header, msg);
return msg;
}
/**
* Special deserializer for pre-alloc'ed message objects.
*
* @param outMsg prealloc'ed msg of the expected type; must be initialized with the corresponding
* deserialization-initializer; must later be uninited/destructed by the caller, no matter whether
* this succeeds or not
* @param expectedMsgType the type of the pre-alloc'ed message object
* @return false on error (e.g. if real msgType does not match expectedMsgType)
*/
bool NetMessageFactory_deserializeFromBuf(App* app, char* recvBuf, size_t bufLen,
NetMessage* outMsg, unsigned short expectedMsgType)
{
NetMessageHeader header;
DeserializeCtx ctx = {
.data = recvBuf,
.length = bufLen,
};
// decode the message header
__NetMessage_deserializeHeader(&ctx, &header);
// verify expected message type
if(unlikely(header.msgType != expectedMsgType) )
return false;
return __NetMessageFactory_deserializeRaw(app, &ctx, &header, outMsg);
}
/**
* @return NetMessage that must be deleted by the caller
* (msg->msgType is NETMSGTYPE_Invalid on error)
*/
NetMessage* NetMessageFactory_createFromMsgType(unsigned short msgType)
{
#define HANDLE(ID, TYPE) case NETMSGTYPE_##ID: return NETMESSAGE_CONSTRUCT(TYPE)
switch(msgType)
{
// control messages
HANDLE(Ack, AckMsgEx);
HANDLE(GenericResponse, GenericResponseMsg);
// nodes messages
HANDLE(GetNodesResp, GetNodesRespMsg);
HANDLE(GetStatesAndBuddyGroupsResp, GetStatesAndBuddyGroupsRespMsg);
HANDLE(GetTargetMappingsResp, GetTargetMappingsRespMsg);
HANDLE(HeartbeatRequest, HeartbeatRequestMsgEx);
HANDLE(Heartbeat, HeartbeatMsgEx);
HANDLE(MapTargets, MapTargetsMsgEx);
HANDLE(RefreshTargetStates, RefreshTargetStatesMsgEx);
HANDLE(RegisterNodeResp, RegisterNodeRespMsg);
HANDLE(RemoveNode, RemoveNodeMsgEx);
HANDLE(RemoveNodeResp, RemoveNodeRespMsg);
HANDLE(SetMirrorBuddyGroup, SetMirrorBuddyGroupMsgEx);
// storage messages
HANDLE(LookupIntentResp, LookupIntentRespMsg);
HANDLE(MkDirResp, MkDirRespMsg);
HANDLE(RmDirResp, RmDirRespMsg);
HANDLE(MkFileResp, MkFileRespMsg);
HANDLE(RefreshEntryInfoResp, RefreshEntryInfoRespMsg);
HANDLE(RenameResp, RenameRespMsg);
HANDLE(HardlinkResp, HardlinkRespMsg);;
HANDLE(UnlinkFileResp, UnlinkFileRespMsg);
HANDLE(ListDirFromOffsetResp, ListDirFromOffsetRespMsg);
HANDLE(SetAttrResp, SetAttrRespMsg);
HANDLE(StatResp, StatRespMsg);
HANDLE(StatStoragePathResp, StatStoragePathRespMsg);
HANDLE(TruncFileResp, TruncFileRespMsg);
HANDLE(ListXAttrResp, ListXAttrRespMsg);
HANDLE(GetXAttrResp, GetXAttrRespMsg);
HANDLE(RemoveXAttrResp, RemoveXAttrRespMsg);
HANDLE(SetXAttrResp, SetXAttrRespMsg);
// session messages
HANDLE(OpenFileResp, OpenFileRespMsg);
HANDLE(CloseFileResp, CloseFileRespMsg);
HANDLE(WriteLocalFileResp, WriteLocalFileRespMsg);
#ifdef BEEGFS_NVFS
HANDLE(WriteLocalFileRDMAResp, WriteLocalFileRDMARespMsg);
#endif
HANDLE(FSyncLocalFileResp, FSyncLocalFileRespMsg);
HANDLE(FLockAppendResp, FLockAppendRespMsg);
HANDLE(FLockEntryResp, FLockEntryRespMsg);
HANDLE(FLockRangeResp, FLockRangeRespMsg);
HANDLE(LockGranted, LockGrantedMsgEx);
HANDLE(BumpFileVersionResp, BumpFileVersionRespMsg);
HANDLE(GetFileVersionResp, GetFileVersionRespMsg);
case NETMSGTYPE_AckNotifyResp: {
SimpleMsg* msg = os_kmalloc(sizeof(*msg));
SimpleMsg_init(msg, msgType);
return &msg->netMessage;
}
default:
{
SimpleMsg* msg = os_kmalloc(sizeof(*msg));
SimpleMsg_init(msg, NETMSGTYPE_Invalid);
return (NetMessage*)msg;
}
}
}

View File

@@ -0,0 +1,12 @@
#ifndef NETMESSAGEFACTORY_H_
#define NETMESSAGEFACTORY_H_
#include <common/Common.h>
#include <common/net/message/NetMessage.h>
extern NetMessage* NetMessageFactory_createFromBuf(App* app, char* recvBuf, size_t bufLen);
extern bool NetMessageFactory_deserializeFromBuf(App* app, char* recvBuf, size_t bufLen,
NetMessage* outMsg, unsigned short expectedMsgType);
extern NetMessage* NetMessageFactory_createFromMsgType(unsigned short msgType);
#endif /*NETMESSAGEFACTORY_H_*/