Enabled read-only -> read/write direction for set_area_protection() for the

simple cases - it might not work properly though, since we don't know yet if
a cache has children; therefore it will print out a warning as a constant
reminder if used in that way. It will still not work if we would need to
insert a new cache inbetween (in case the cache has children or only read-only
areas (even if there is no way yet to specify how exactly the VM should behave
in this case yet).
Added a comment to vm_map_file() about what we still need to do there.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11751 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-03-15 02:35:32 +00:00
parent 2a74bc0fcb
commit 9191c9ddc8

View File

@ -1029,6 +1029,13 @@ _vm_map_file(aspace_id aid, const char *name, void **_address, uint32 addressSpe
void *vnode;
status_t status;
// ToDo: maybe attach to an FD, not a path (or both, like VFS calls)
// ToDo: check file access permissions (would be already done if the above were true)
// ToDo: for binary files, we want to make sure that they get the
// copy of a file at a given time, ie. later changes should not
// make it into the mapped copy -- this will need quite some changes
// to be done in a nice way
vm_address_space *aspace = vm_get_aspace_by_id(aid);
if (aspace == NULL)
return ERR_VM_INVALID_ASPACE;
@ -1403,6 +1410,22 @@ err:
}
static int32
count_writable_areas(vm_cache_ref *ref, vm_area *ignoreArea)
{
struct vm_area *area = ref->areas;
uint32 count = 0;
for (; area != NULL; area = area->cache_next) {
if (area != ignoreArea
&& (area->protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) != 0)
count++;
}
return count;
}
static status_t
vm_set_area_protection(aspace_id aspaceID, area_id areaID, uint32 newProtection)
{
@ -1441,15 +1464,7 @@ vm_set_area_protection(aspace_id aspaceID, area_id areaID, uint32 newProtection)
// change from read/write to read-only
if (cache->source != NULL && cache->temporary) {
uint32 writableAreas = 0;
struct vm_area *cacheArea = cacheRef->areas;
for (; cacheArea != NULL; cacheArea = cacheArea->cache_next) {
if (cacheArea != area
&& (cacheArea->protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) != 0)
writableAreas++;
}
if (writableAreas == 0) {
if (count_writable_areas(cacheRef, area) == 0) {
// Since this cache now lives from the pages in its source cache,
// we can change the cache's commitment to take only those pages
// into account that really are in this cache.
@ -1464,16 +1479,30 @@ vm_set_area_protection(aspace_id aspaceID, area_id areaID, uint32 newProtection)
status = cache->store->ops->commit(cache->store, count * B_PAGE_SIZE);
// ToDo: we may be able to join with our source cache, if any
// ToDo: we may be able to join with our source cache, if count == 0
}
}
} else if ((area->protection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) == 0
&& (newProtection & (B_WRITE_AREA | B_KERNEL_WRITE_AREA)) != 0) {
// change from read-only to read/write
// ToDo: if this is a shared cache, insert new cache
// ToDo: eventually change commitment
status = B_ERROR;
// ToDo: if this is a shared cache, insert new cache (we only know about other
// areas in this cache yet, though, not about child areas)
// -> use this call with care, it might currently have unwanted consequences
// because of this. It should always be safe though, if there are no other
// (child) areas referencing this area's cache (you just might not know).
if (count_writable_areas(cacheRef, area) == 0
&& (cacheRef->areas != area || area->cache_next)) {
// ToDo: child areas are not tested for yet
dprintf("set_area_protection(): warning, would need to insert a new cache_ref (not yet implemented)!\n");
status = B_NOT_ALLOWED;
} else
dprintf("set_area_protection() may not work correctly yet in this direction!\n");
if (status == B_OK && cache->source != NULL && cache->temporary) {
// the cache's commitment must contain all possible pages
status = cache->store->ops->commit(cache->store, cache->virtual_size);
}
} else {
// we don't have anything special to do in all other cases
}