packagefs: Add a fallback buffer for reading heaps in low-memory conditions.

Otherwise we might fail with B_NO_MEMORY, or wait for long periods of
time, which we don't want to do in such a critical routine.

Should improve system responsiveness (or even prevent application
crashes) under high memory pressure.
This commit is contained in:
Augustin Cavalier
2026-02-04 14:59:27 -05:00
parent 685d305a5b
commit dce3a4366d
3 changed files with 19 additions and 4 deletions
@@ -100,6 +100,7 @@ public:
static const size_t kChunkSize = 64 * 1024; static const size_t kChunkSize = 64 * 1024;
#if defined(_KERNEL_MODE) #if defined(_KERNEL_MODE)
static void* sQuadChunkCache; static void* sQuadChunkCache;
static void* sQuadChunkFallbackBuffer;
#endif #endif
protected: protected:
@@ -1153,7 +1153,8 @@ packagefs_std_ops(int32 op, ...)
create_object_cache("pkgfs heap buffers", create_object_cache("pkgfs heap buffers",
PackageFileHeapAccessorBase::kChunkSize * 4, PackageFileHeapAccessorBase::kChunkSize * 4,
0); 0);
object_cache_set_minimum_reserve(quadChunkCache, 1); PackageFileHeapAccessorBase::sQuadChunkFallbackBuffer =
object_cache_alloc(quadChunkCache, 0);
TwoKeyAVLTreeNode<void*>::sNodeCache = TwoKeyAVLTreeNode<void*>::sNodeCache =
create_object_cache("pkgfs TKAVLTreeNodes", create_object_cache("pkgfs TKAVLTreeNodes",
@@ -1176,6 +1177,9 @@ packagefs_std_ops(int32 op, ...)
PRINT("package_std_ops(): B_MODULE_UNINIT\n"); PRINT("package_std_ops(): B_MODULE_UNINIT\n");
PackageFSRoot::GlobalUninit(); PackageFSRoot::GlobalUninit();
delete_object_cache(TwoKeyAVLTreeNode<void*>::sNodeCache); delete_object_cache(TwoKeyAVLTreeNode<void*>::sNodeCache);
object_cache_free((object_cache*)
PackageFileHeapAccessorBase::sQuadChunkCache,
PackageFileHeapAccessorBase::sQuadChunkFallbackBuffer, 0);
delete_object_cache((object_cache*) delete_object_cache((object_cache*)
PackageFileHeapAccessorBase::sQuadChunkCache); PackageFileHeapAccessorBase::sQuadChunkCache);
StringConstants::Cleanup(); StringConstants::Cleanup();
@@ -11,7 +11,8 @@
#include <algorithm> #include <algorithm>
#include <new> #include <new>
#ifdef _KERNEL_MODE #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
#include <util/AutoLock.h>
#include <slab/Slab.h> #include <slab/Slab.h>
#endif #endif
@@ -30,8 +31,10 @@ namespace BHPKG {
namespace BPrivate { namespace BPrivate {
#if defined(_KERNEL_MODE) #if defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
void* PackageFileHeapAccessorBase::sQuadChunkCache = NULL; void* PackageFileHeapAccessorBase::sQuadChunkCache = NULL;
void* PackageFileHeapAccessorBase::sQuadChunkFallbackBuffer = NULL;
static mutex sFallbackBufferLock = MUTEX_INITIALIZER("PackageFileHeapAccessorBase fallback buffer");
#endif #endif
@@ -239,9 +242,16 @@ PackageFileHeapAccessorBase::ReadDataToOutput(off_t offset, size_t size,
}; };
ObjectCacheDeleter chunkBufferDeleter((object_cache*)sQuadChunkCache); ObjectCacheDeleter chunkBufferDeleter((object_cache*)sQuadChunkCache);
uint8* quadChunkBuffer = (uint8*)object_cache_alloc((object_cache*)sQuadChunkCache, 0); uint8* quadChunkBuffer = (uint8*)object_cache_alloc((object_cache*)sQuadChunkCache,
CACHE_DONT_WAIT_FOR_MEMORY);
chunkBufferDeleter.object = quadChunkBuffer; chunkBufferDeleter.object = quadChunkBuffer;
MutexLocker fallbackBufferLocker(sFallbackBufferLock, false, false);
if (quadChunkBuffer == NULL) {
fallbackBufferLocker.Lock();
quadChunkBuffer = (uint8*)sQuadChunkFallbackBuffer;
}
// segment data buffer // segment data buffer
iovec localScratch; iovec localScratch;
compressedDataBuffer = (uint16*)(quadChunkBuffer + 0); compressedDataBuffer = (uint16*)(quadChunkBuffer + 0);