Commit 132fe3f9 authored by Christian Mohrbacher's avatar Christian Mohrbacher

Merge branch 'v6-modsync-errors' into 'v6'

V6 modsync errors

See merge request !224
parents f1d9b009 1c316f79
......@@ -183,14 +183,6 @@ class MirroredMessage : public BaseT
// pairs with the memory barrier before acquireMirrorStateSlot
__sync_synchronize();
if (responsePtr && buddyCommSuccessful)
responsePtr->sendResponse(ctx);
else if (!buddyCommSuccessful)
ctx.sendResponse(
GenericResponseMsg(
GenericRespMsgCode_INDIRECTCOMMERR_NOTAGAIN,
"Communication with secondary failed"));
if (BuddyResyncer::getSyncChangeset())
{
if (isMirrored() &&
......@@ -202,6 +194,14 @@ class MirroredMessage : public BaseT
BuddyResyncer::abandonSyncChangeset();
}
if (responsePtr && buddyCommSuccessful)
responsePtr->sendResponse(ctx);
else if (!buddyCommSuccessful)
ctx.sendResponse(
GenericResponseMsg(
GenericRespMsgCode_INDIRECTCOMMERR_NOTAGAIN,
"Communication with secondary failed"));
lockState = {};
}
......
......@@ -9,13 +9,16 @@
#include "HardlinkMsgEx.h"
std::tuple<DirIDLock, ParentNameLock, ParentNameLock> HardlinkMsgEx::lock(EntryLockStore& store)
std::tuple<DirIDLock, ParentNameLock, ParentNameLock, FileIDLock> HardlinkMsgEx::lock(
EntryLockStore& store)
{
// NOTE: normally we'd need to also lock on the MDS holding the destination file,
// but we don't support hardlinks to different servers, yet
ParentNameLock fromLock;
ParentNameLock toLock;
FileIDLock fileLock;
DirIDLock dirLock(&store, getToDirInfo()->getEntryID(), true);
// take care about lock ordering! see MirroredMessage::lock()
......@@ -37,10 +40,27 @@ std::tuple<DirIDLock, ParentNameLock, ParentNameLock> HardlinkMsgEx::lock(EntryL
fromLock = {&store, getFromDirInfo()->getEntryID(), getFromName()};
}
// hardlinking modifies the file inode link count, so we have to lock the file. if we can't
// reference the directory, or if the file does not exist, we can continue - the directory is
// locked, so the file cannot suddenly appear after we return here.
auto dir = Program::getApp()->getMetaStore()->referenceDir(getFromDirInfo()->getEntryID(),
getFromInfo()->getIsBuddyMirrored(), true);
if (dir)
{
EntryInfo fromInfo;
dir->getFileEntryInfo(getFromName(), fromInfo);
if (DirEntryType_ISFILE(fromInfo.getEntryType()))
fileLock = {&store, fromInfo.getEntryID()};
Program::getApp()->getMetaStore()->releaseDir(dir->getID());
}
return std::make_tuple(
std::move(dirLock),
std::move(fromLock),
std::move(toLock));
std::move(toLock),
std::move(fileLock));
}
bool HardlinkMsgEx::processIncoming(ResponseContext& ctx)
......
......@@ -10,14 +10,15 @@
#include <net/message/MirroredMessage.h>
class HardlinkMsgEx : public MirroredMessage<HardlinkMsg,
std::tuple<DirIDLock, ParentNameLock, ParentNameLock>>
std::tuple<DirIDLock, ParentNameLock, ParentNameLock, FileIDLock>>
{
public:
typedef ErrorCodeResponseState<HardlinkRespMsg, NETMSGTYPE_Hardlink> ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<DirIDLock, ParentNameLock, ParentNameLock> lock(EntryLockStore& store) override;
std::tuple<DirIDLock, ParentNameLock, ParentNameLock, FileIDLock>
lock(EntryLockStore& store) override;
bool isMirrored() override { return getToDirInfo()->getIsBuddyMirrored(); }
......
......@@ -12,7 +12,8 @@
// Called from fhgfs-ctl (online_cfg) to create a file on a specific node.
std::tuple<DirIDLock, ParentNameLock> MkFileWithPatternMsgEx::lock(EntryLockStore& store)
std::tuple<DirIDLock, ParentNameLock, FileIDLock> MkFileWithPatternMsgEx::lock(
EntryLockStore& store)
{
// no need to lock the created file as well, since
// a) no other operation can create the same file id
......@@ -20,8 +21,9 @@ std::tuple<DirIDLock, ParentNameLock> MkFileWithPatternMsgEx::lock(EntryLockStor
// c) if bulk resync gets the file while it is incomplete, individual resync will get it again
DirIDLock dirLock(&store, getParentInfo()->getEntryID(), true);
ParentNameLock dentryLock(&store, getParentInfo()->getEntryID(), getNewFileName());
FileIDLock fileLock(&store, entryID);
return std::make_tuple(std::move(dirLock), std::move(dentryLock));
return std::make_tuple(std::move(dirLock), std::move(dentryLock), std::move(fileLock));
}
bool MkFileWithPatternMsgEx::processIncoming(ResponseContext& ctx)
......
......@@ -14,7 +14,7 @@
* or from ioctl calls.
*/
class MkFileWithPatternMsgEx : public MirroredMessage<MkFileWithPatternMsg,
std::tuple<DirIDLock, ParentNameLock>>
std::tuple<DirIDLock, ParentNameLock, FileIDLock>>
{
public:
typedef ErrorAndEntryResponseState<MkFileWithPatternRespMsg, NETMSGTYPE_MkFileWithPattern>
......@@ -22,7 +22,7 @@ class MkFileWithPatternMsgEx : public MirroredMessage<MkFileWithPatternMsg,
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<DirIDLock, ParentNameLock> lock(EntryLockStore& store) override;
std::tuple<DirIDLock, ParentNameLock, FileIDLock> lock(EntryLockStore& store) override;
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
......
......@@ -12,6 +12,8 @@ bool MovingDirInsertMsgEx::processIncoming(ResponseContext& ctx)
LOG_DEBUG_CONTEXT(log, 4, "Received a MovingDirInsertMsg from: " + ctx.peerName() );
rctx = &ctx;
return BaseType::processIncoming(ctx);
}
......
......@@ -9,7 +9,8 @@
// Move directory to another meta-data server
class MovingDirInsertMsgEx : public MirroredMessage<MovingDirInsertMsg, DirIDLock>
class MovingDirInsertMsgEx : public MirroredMessage<MovingDirInsertMsg,
std::tuple<DirIDLock, ParentNameLock>>
{
public:
typedef ErrorCodeResponseState<MovingDirInsertRespMsg, NETMSGTYPE_MovingDirInsert>
......@@ -17,21 +18,25 @@ class MovingDirInsertMsgEx : public MirroredMessage<MovingDirInsertMsg, DirIDLoc
virtual bool processIncoming(ResponseContext& ctx) override;
DirIDLock lock(EntryLockStore& store) override
std::tuple<DirIDLock, ParentNameLock> lock(EntryLockStore& store) override
{
// we must not lock the directory if it is owned by the current node. if it is, the
// current message was also sent by the local node, specifically by a RmDirMsgEx, which
// also locks the directory for write
uint16_t localID = Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID();
if (getToDirInfo()->getOwnerNodeID().val() == localID)
if (rctx->isLocallyGenerated())
return {};
return {&store, getToDirInfo()->getEntryID(), true};
DirIDLock dirLock(&store, getToDirInfo()->getEntryID(), true);
ParentNameLock nameLock(&store, getToDirInfo()->getEntryID(), getNewName());
return std::make_tuple(std::move(dirLock), std::move(nameLock));
}
bool isMirrored() override { return getToDirInfo()->getIsBuddyMirrored(); }
private:
ResponseContext* rctx;
std::unique_ptr<MirroredMessageResponseState> executeLocally(ResponseContext& ctx,
bool isSecondary) override;
......
......@@ -9,6 +9,61 @@
#include "MovingFileInsertMsgEx.h"
std::tuple<FileIDLock, FileIDLock, DirIDLock, ParentNameLock> MovingFileInsertMsgEx::lock(
EntryLockStore& store)
{
// we must not lock the directory if it is owned by the current node. if it is, the
// current message was also sent by the local node, specifically by a rename msg, which
// also locks the directory for write
if (rctx->isLocallyGenerated())
return {};
DirIDLock dirLock(&store, getToDirInfo()->getEntryID(), true);
ParentNameLock nameLock(&store, getToDirInfo()->getEntryID(), getNewName());
FileIDLock newLock;
FileIDLock unlinkedLock;
auto dir = Program::getApp()->getMetaStore()->referenceDir(getToDirInfo()->getEntryID(),
getToDirInfo()->getIsBuddyMirrored(), true);
if (dir)
{
FileInode newInode;
Deserializer des(getSerialBuf(), getSerialBufLen());
newInode.deserializeMetaData(des);
if (des.good())
{
std::string unlinkedID = newInode.getEntryID();
EntryInfo unlinkedInfo;
dir->getFileEntryInfo(getNewName(), unlinkedInfo);
if (DirEntryType_ISFILE(unlinkedInfo.getEntryType()))
unlinkedID = unlinkedInfo.getEntryID();
if (newInode.getEntryID() < unlinkedID)
{
newLock = {&store, newInode.getEntryID()};
unlinkedLock = {&store, unlinkedID};
}
else if (newInode.getEntryID() == unlinkedID)
{
newLock = {&store, newInode.getEntryID()};
}
else
{
unlinkedLock = {&store, unlinkedID};
newLock = {&store, newInode.getEntryID()};
}
}
}
return std::make_tuple(
std::move(newLock),
std::move(unlinkedLock),
std::move(dirLock),
std::move(nameLock));
}
bool MovingFileInsertMsgEx::processIncoming(ResponseContext& ctx)
{
......@@ -39,9 +94,7 @@ std::unique_ptr<MirroredMessageResponseState> MovingFileInsertMsgEx::executeLoca
return boost::make_unique<MovingFileInsertResponseState>(FhgfsOpsErr_PATHNOTEXISTS);
FhgfsOpsErr moveRes = metaStore->moveRemoteFileInsert(
fromFileInfo, *toDir, newName,
getSerialBuf(), getSerialBufLen(), &unlinkInode, newFileInfo, std::get<0>(lockState),
std::get<1>(lockState));
fromFileInfo, *toDir, newName, getSerialBuf(), getSerialBufLen(), &unlinkInode, newFileInfo);
if (moveRes != FhgfsOpsErr_SUCCESS)
{
metaStore->releaseDir(toDir->getID());
......
......@@ -68,34 +68,21 @@ class MovingFileInsertResponseState : public MirroredMessageResponseState
};
class MovingFileInsertMsgEx : public MirroredMessage<MovingFileInsertMsg,
std::tuple<FileIDLock, FileIDLock, DirIDLock>>
std::tuple<FileIDLock, FileIDLock, DirIDLock, ParentNameLock>>
{
public:
typedef MovingFileInsertResponseState ResponseState;
virtual bool processIncoming(ResponseContext& ctx) override;
std::tuple<FileIDLock, FileIDLock, DirIDLock> lock(EntryLockStore& store) override
{
// the created file need not be locked, because only the requestor of the move operations
// knows the new parent of the file, and only knows it for certain once the origin server
// has acknowledged the operation.
// we must not lock the directory if it is owned by the current node. if it is, the
// current message was also sent by the local node, specifically by a RmDirMsgEx, which
// also locks the directory for write
uint16_t localID = Program::getApp()->getMetaBuddyGroupMapper()->getLocalGroupID();
if (getToDirInfo()->getOwnerNodeID().val() == localID)
return {};
return std::make_tuple(
FileIDLock(), // new file inode
FileIDLock(), // (maybe) overwritten file inode
DirIDLock(&store, getToDirInfo()->getEntryID(), true));
}
std::tuple<FileIDLock, FileIDLock, DirIDLock, ParentNameLock>
lock(EntryLockStore& store) override;
bool isMirrored() override { return getToDirInfo()->getIsBuddyMirrored(); }
private:
ResponseContext* rctx;
StringVector xattrNames;
EntryInfo newFileInfo;
MsgHelperXAttr::StreamXAttrState streamState;
......
......@@ -298,7 +298,8 @@ FhgfsOpsErr RenameV2MsgEx::renameDir(DirInode& fromParent, EntryInfo* fromDirInf
rmDirEntry->getEntryInfo(parentID, 0, &removedInfo);
updateRenamedDirInode(&removedInfo, toDirInfo);
if (!hasFlag(NetMessageHeader::Flag_BuddyMirrorSecond))
updateRenamedDirInode(&removedInfo, toDirInfo);
}
else
{
......
......@@ -69,8 +69,7 @@ class MetaStore
FhgfsOpsErr moveRemoteFileInsert(EntryInfo* fromFileInfo, DirInode& toParent,
const std::string& newEntryName, const char* buf,
uint32_t bufLen, std::unique_ptr<FileInode>* outUnlinkedFile, EntryInfo& newFileInfo,
FileIDLock& newFileLock, FileIDLock& oldFileLock);
uint32_t bufLen, std::unique_ptr<FileInode>* outUnlinkedFile, EntryInfo& newFileInfo);
FhgfsOpsErr moveRemoteFileBegin(DirInode& dir, EntryInfo* entryInfo, char* buf, size_t bufLen,
size_t* outUsedBufLen);
......
......@@ -331,8 +331,7 @@ FhgfsOpsErr MetaStore::checkRenameOverwrite(EntryInfo* fromEntry, EntryInfo* ove
*/
FhgfsOpsErr MetaStore::moveRemoteFileInsert(EntryInfo* fromFileInfo, DirInode& toParent,
const std::string& newEntryName, const char* buf, uint32_t bufLen,
std::unique_ptr<FileInode>* outUnlinkedInode, EntryInfo& newFileInfo, FileIDLock& newFileLock,
FileIDLock& oldFileLock)
std::unique_ptr<FileInode>* outUnlinkedInode, EntryInfo& newFileInfo)
{
// note: we do not allow newEntry to be a file if the old entry was a directory (and vice versa)
const char* logContext = "rename(): Insert remote entry";
......@@ -363,12 +362,6 @@ FhgfsOpsErr MetaStore::moveRemoteFileInsert(EntryInfo* fromFileInfo, DirInode& t
goto outUnlock;
}
// if we overwrite an existing dentry, the inode behind the dentry will be either updated or
// unlinked, thus requiring a lock.
if (toParent.getIsBuddyMirrored() && overWriteInfo.getIsInlined())
oldFileLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(),
overWriteInfo.getEntryID()};
// only unlink the dir-entry-name here, so we can still restore it from dir-entry-id
FhgfsOpsErr unlinkRes = toParent.unlinkDirEntryUnlocked(newEntryName, overWrittenEntry,
DirEntry_UNLINK_FILENAME);
......@@ -418,19 +411,6 @@ FhgfsOpsErr MetaStore::moveRemoteFileInsert(EntryInfo* fromFileInfo, DirInode& t
retVal = FhgfsOpsErr_INTERNAL;
}
if (retVal == FhgfsOpsErr_SUCCESS)
{
// since this entry ID was not previously present on this node, and toParent is locked for
// write, no other thread can lock the entry ID.
// beware: the caller is responsible for locking an inlined file inode for the name if both
// source and target live on the same node!
if (toParent.getIsBuddyMirrored() && fromFileInfo->getIsInlined() &&
(!fromFileInfo->getIsBuddyMirrored() ||
fromFileInfo->getOwnerNodeID() != toParent.ownerNodeID))
newFileLock = {Program::getApp()->getMirroredSessions()->getEntryLockStore(),
newFileInfo.getEntryID()};
}
if (overWrittenEntry && retVal == FhgfsOpsErr_SUCCESS)
{ // unlink the overwritten entry, will unlock, release and return
bool unlinkedWasInlined = overWrittenEntry->getIsInodeInlined();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment