packagefs: Fix missing unlocks in Volume package content node removal.
When breaking out of _RemovePackageContentRootNode() by encountering a specified "endPackageNode", we need to unlock all directories. This case is only possible to encounter when _AddPackageContentRootNode() fails partway and invokes _Remove() to remove the just-added nodes. Fixes a hang/deadlock encountered by Diver while testing some (disabled) HaikuPorts recipes.
This commit is contained in:
parent
3e2b187899
commit
d6b37ce996
@ -1032,7 +1032,7 @@ Volume::_RemovePackageContent(Package* package, PackageNode* endNode,
|
|||||||
node = nextNode;
|
node = nextNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
fPackageFSRoot->RemovePackage(package);;
|
fPackageFSRoot->RemovePackage(package);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1046,6 +1046,8 @@ status_t
|
|||||||
Volume::_AddPackageContentRootNode(Package* package,
|
Volume::_AddPackageContentRootNode(Package* package,
|
||||||
PackageNode* rootPackageNode, bool notify)
|
PackageNode* rootPackageNode, bool notify)
|
||||||
{
|
{
|
||||||
|
ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
|
||||||
|
|
||||||
PackageNode* packageNode = rootPackageNode;
|
PackageNode* packageNode = rootPackageNode;
|
||||||
Directory* directory = fRootDirectory;
|
Directory* directory = fRootDirectory;
|
||||||
directory->WriteLock();
|
directory->WriteLock();
|
||||||
@ -1099,6 +1101,8 @@ Volume::_AddPackageContentRootNode(Package* package,
|
|||||||
} while (packageNode != NULL);
|
} while (packageNode != NULL);
|
||||||
} while (packageNode != NULL);
|
} while (packageNode != NULL);
|
||||||
|
|
||||||
|
ASSERT(directory == NULL);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1113,13 +1117,21 @@ void
|
|||||||
Volume::_RemovePackageContentRootNode(Package* package,
|
Volume::_RemovePackageContentRootNode(Package* package,
|
||||||
PackageNode* rootPackageNode, PackageNode* endPackageNode, bool notify)
|
PackageNode* rootPackageNode, PackageNode* endPackageNode, bool notify)
|
||||||
{
|
{
|
||||||
|
ASSERT_WRITE_LOCKED_RW_LOCK(&fLock);
|
||||||
|
|
||||||
PackageNode* packageNode = rootPackageNode;
|
PackageNode* packageNode = rootPackageNode;
|
||||||
Directory* directory = fRootDirectory;
|
Directory* directory = fRootDirectory;
|
||||||
directory->WriteLock();
|
directory->WriteLock();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (packageNode == endPackageNode)
|
if (packageNode == endPackageNode) {
|
||||||
|
// unlock all directories
|
||||||
|
while (directory != NULL) {
|
||||||
|
directory->WriteUnlock();
|
||||||
|
directory = directory->Parent();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// recurse into directory
|
// recurse into directory
|
||||||
if (PackageDirectory* packageDirectory
|
if (PackageDirectory* packageDirectory
|
||||||
@ -1157,6 +1169,8 @@ Volume::_RemovePackageContentRootNode(Package* package,
|
|||||||
// the parent is still locked, so this is safe
|
// the parent is still locked, so this is safe
|
||||||
} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
|
} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
|
||||||
} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
|
} while (packageNode != NULL/* && packageNode != rootPackageNode*/);
|
||||||
|
|
||||||
|
ASSERT(directory == NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user