From 87079731d38f036344fe00d9d295e5c4658b05a4 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 12 Jul 2025 15:13:41 -0400 Subject: [PATCH] kernel/vm: Don't invoke compute_area_page_commitment in map_backing_store. It seems this is still too early and not enough fields in the VMArea have been initialized. Instead just check the protection manually. Also fix some more locking behavior in the error path. --- src/system/kernel/vm/vm.cpp | 47 +++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index 6f68d97c0c..e26c4ebdea 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -1264,18 +1264,16 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset, cache = newCache; } - // attach the cache to the area - area->cache = cache; - area->cache_offset = offset; - - // point the cache back to the area - cache->InsertAreaLocked(area); - if ((flags & CREATE_AREA_DONT_COMMIT_MEMORY) == 0) { - const size_t commitmentPages = compute_area_page_commitment(area); - status = cache->SetMinimalCommitment(commitmentPages * B_PAGE_SIZE, priority); - if (status != B_OK) - goto err2; + uint32 commitProtection = B_WRITE_AREA | B_KERNEL_WRITE_AREA; + if (cache->source == NULL) + commitProtection |= B_READ_AREA | B_KERNEL_READ_AREA; + + if ((protection & commitProtection) != 0) { + status = cache->SetMinimalCommitment(size, priority); + if (status != B_OK) + goto err2; + } } // check to see if this address space has entered DELETE state @@ -1310,6 +1308,12 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset, if (status != B_OK) goto err2; + // attach the cache to the area + area->cache = cache; + area->cache_offset = offset; + + // point the cache back to the area + cache->InsertAreaLocked(area); if (mapping == REGION_PRIVATE_MAP) cache->Unlock(); @@ -1328,21 +1332,24 @@ map_backing_store(VMAddressSpace* addressSpace, VMCache* cache, off_t offset, return B_OK; err3: - cache->Lock(); + if (mapping != REGION_PRIVATE_MAP) + cache->Unlock(); + cache->RemoveArea(area); + area->cache = NULL; + if (mapping != REGION_PRIVATE_MAP) + cache->Lock(); + addressSpace->RemoveArea(area, allocationFlags); err2: - cache->Unlock(); - cache->RemoveArea(area); - cache->Lock(); - area->cache = NULL; - if (mapping == REGION_PRIVATE_MAP) { // We created this cache, so we must delete it again. Note, that we // need to temporarily unlock the source cache or we'll otherwise // deadlock, since VMCache::_RemoveConsumer() will try to lock it, too. - sourceCache->Unlock(); - cache->ReleaseRefAndUnlock(); - sourceCache->Lock(); + if (sourceCache != cache) + sourceCache->Unlock(); + cache->ReleaseRef(); + if (sourceCache != cache) + sourceCache->Lock(); } err1: addressSpace->DeleteArea(area, allocationFlags);