Commit 12ccc042 authored by Phoebe Buckheister's avatar Phoebe Buckheister 🦎

meta: lock file inode during hardlink

hardlinking modifies the inode link count (among other things) and will
thus modsync the inode during resync, so it must be locked.

(cherry picked from commit dc0ee14ed596553bae1d0c3e9410d6cc7a4bee91)
parent 6ae44283
......@@ -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(); }
......
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