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.
This commit is contained in:
Augustin Cavalier
2025-07-12 15:13:41 -04:00
parent 3978032551
commit 87079731d3
+27 -20
View File
@@ -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);