From d6b37ce996026eaa1da45615fc3dd8434b8666c4 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 21 Sep 2023 14:53:06 -0400 Subject: [PATCH] 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. --- .../file_systems/packagefs/volume/Volume.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp index 595eb04713..e53f0f252d 100644 --- a/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp +++ b/src/add-ons/kernel/file_systems/packagefs/volume/Volume.cpp @@ -1032,7 +1032,7 @@ Volume::_RemovePackageContent(Package* package, PackageNode* endNode, node = nextNode; } - fPackageFSRoot->RemovePackage(package);; + fPackageFSRoot->RemovePackage(package); } @@ -1046,6 +1046,8 @@ status_t Volume::_AddPackageContentRootNode(Package* package, PackageNode* rootPackageNode, bool notify) { + ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); + PackageNode* packageNode = rootPackageNode; Directory* directory = fRootDirectory; directory->WriteLock(); @@ -1099,6 +1101,8 @@ Volume::_AddPackageContentRootNode(Package* package, } while (packageNode != NULL); } while (packageNode != NULL); + ASSERT(directory == NULL); + return B_OK; } @@ -1113,13 +1117,21 @@ void Volume::_RemovePackageContentRootNode(Package* package, PackageNode* rootPackageNode, PackageNode* endPackageNode, bool notify) { + ASSERT_WRITE_LOCKED_RW_LOCK(&fLock); + PackageNode* packageNode = rootPackageNode; Directory* directory = fRootDirectory; directory->WriteLock(); do { - if (packageNode == endPackageNode) + if (packageNode == endPackageNode) { + // unlock all directories + while (directory != NULL) { + directory->WriteUnlock(); + directory = directory->Parent(); + } break; + } // recurse into directory if (PackageDirectory* packageDirectory @@ -1157,6 +1169,8 @@ Volume::_RemovePackageContentRootNode(Package* package, // the parent is still locked, so this is safe } while (packageNode != NULL/* && packageNode != rootPackageNode*/); } while (packageNode != NULL/* && packageNode != rootPackageNode*/); + + ASSERT(directory == NULL); }