Commit d3ba2440 authored by Phoebe Buckheister's avatar Phoebe Buckheister 🦎

meta: during rename, lock target name if fromDir != toDir

the locking code correctly enforces directory lock ordering using the
order on (fromDirID, forWrite). it also correctly enforces lock
ordering on parent/name combinations on (parentID, name).

if oldName and newName are the same though it does not correctly lock
(toDirID, newName).

(cherry picked from commit a8e6b9d0e217437812fe6cd4624382d97808d768)
parent 93d2a1ff
......@@ -34,27 +34,40 @@ RenameV2Locks RenameV2MsgEx::lock(EntryLockStore& store)
// take care about lock ordering! see MirroredMessage::lock()
// since directories are locked for read, and by the same id as the (parent,name) tuples,the
// same ordering applies.
if (getFromDirInfo()->getEntryID() < getToDirInfo()->getEntryID()
|| (getFromDirInfo()->getEntryID() == getToDirInfo()->getEntryID()
&& getOldName() < getNewName()))
if (getFromDirInfo()->getEntryID() < getToDirInfo()->getEntryID())
{
result.fromDirLock = {&store, getFromDirInfo()->getEntryID(), true};
if (getFromDirInfo()->getEntryID() != getToDirInfo()->getEntryID())
result.toDirLock = {&store, getToDirInfo()->getEntryID(), true};
result.toDirLock = {&store, getToDirInfo()->getEntryID(), true};
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
if (getOldName() != getNewName())
result.toNameLock = {&store, getToDirInfo()->getEntryID(), getNewName()};
}
else if (getFromDirInfo()->getEntryID() == getToDirInfo()->getEntryID())
{
result.fromDirLock = {&store, getFromDirInfo()->getEntryID(), true};
if (getOldName() < getNewName())
{
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
result.toNameLock = {&store, getToDirInfo()->getEntryID(), getNewName()};
}
else if (getOldName() == getNewName())
{
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
}
else
{
result.toNameLock = {&store, getToDirInfo()->getEntryID(), getNewName()};
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
}
}
else
{
result.toDirLock = {&store, getToDirInfo()->getEntryID(), true};
if (getFromDirInfo()->getEntryID() != getToDirInfo()->getEntryID())
result.fromDirLock = {&store, getFromDirInfo()->getEntryID(), true};
result.fromDirLock = {&store, getFromDirInfo()->getEntryID(), true};
result.toNameLock = {&store, getToDirInfo()->getEntryID(), getNewName()};
if (getOldName() != getNewName())
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
result.fromNameLock = {&store, getFromDirInfo()->getEntryID(), getOldName()};
}
EntryInfo fromFileInfo;
......@@ -62,6 +75,12 @@ RenameV2Locks RenameV2MsgEx::lock(EntryLockStore& store)
DirInode* fromDir = metaStore->referenceDir(getFromDirInfo()->getEntryID(),
getFromDirInfo()->getIsBuddyMirrored(), true);
// if the directory could not be referenced it does not exist on the current node. this will
// cause the operation to fail lateron during executeLocally() when we reference the same
// directory again. since we cannot do anything without having access to the source directory,
// and since no directory with the same id as the source directory can appear after the source
// directory has been removed, we can safely unlock everything right here and continue without
// blocking other workers on the (probably live) target directory.
if (!fromDir)
return {};
else
......@@ -82,7 +101,7 @@ RenameV2Locks RenameV2MsgEx::lock(EntryLockStore& store)
result.fromFileLock = {&store, fromFileInfo.getEntryID()};
result.unlinkedFileLock = {&store, toFileInfo.getEntryID()};
}
else if (fromFileInfo.getEntryID() < toFileInfo.getEntryID())
else if (fromFileInfo.getEntryID() == toFileInfo.getEntryID())
{
result.fromFileLock = {&store, fromFileInfo.getEntryID()};
}
......
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