On Sat, Apr 15, 2000 at 08:13:20PM -0700, Matthew Dillon wrote:
>
> :Here's what I worry about: We only clear OBJ_ONEMAPPING on the top-level
> :object, and none of its backing objects. Nothing guarantees that these
> :backing objects have OBJ_ONEMAPPING cleared. The page that we're "double"
> :mapping may, however, reside in one of its backing objects. This is
> :bad.
>
> I don't think this is an issue. The only double-mapped pages we care
> about are those at the top-level (vm_object's connected directly to a
> vm_map_entry). This is because these are the only pages effected by
> write-faults and copy-on-write issues.
>
I disagree. If a backing object (BO) has OBJ_ONEMAPPING set, and someone
call vm_map_delete(map, start, end) on an address space that references
BO directly, then the system will crash and burn because vm_map_delete
will (incorrectly) free physical pages:
...
pmap_remove(map->pmap, s, e);
if (object != NULL &&
object->ref_count != 1 &&
(object->flags & (OBJ_NOSPLIT|OBJ_ONEMAPPING)) == OBJ_ONEMAPPING &&
(object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) {
vm_object_collapse(object);
vm_object_page_remove(object, offidxstart, offidxend, FALSE);
^^^^^^^^^^^^^^^^^^^^^
The reason why John Dyson introduced OBJ_ONEMAPPING was so that he
could know that physical pages were unreferenced (and thus free the pages)
even though the object's ref count > 1. He was spurred on by the UVM
work, which accomplished the same thing via per-page reference counting.
> For example, if you dirty a page that is mapped privately the system must
> copy-on-write the page. More importantly, if you fork() and either parent
> or child dirties what is now a shared page, they need to copy on write
> and the other process cannot see that change. OBJ_ONEMAPPING is an
> optimization that allows a process to dirty an anonymous (not vnode-backed)
> page without doing a copy-on-write in the case where that process is
> the ONLY process mapping the page.
>
Umm, it can do this without the OBJ_ONEMAPPING attribute, because
the ref count on the object == 1. Note that the code from vm_object_shadow
doesn't even check OBJ_ONEMAPPING:
/*
* Don't create the new object if the old object isn't shared.
*/
if (source != NULL &&
source->ref_count == 1 &&
source->handle == NULL &&
(source->type == OBJT_DEFAULT ||
source->type == OBJT_SWAP))
return;
> Copy-on-write is an issue that only effects the top level object. So
> we shouldn't care whether OBJ_ONEMAPPING is set or cleared in deeper
> objects.
>
I do care, because I don't want those pages freed by a vm_map_delete.
> Copying a page that was previously shared is an expensive operation not
> only in having to do the copy, but also in having to split the vm_map_entry
> and create a new holding vm_object to hold the copy. This new object must
> have OBJ_ONEMAPPING set so that when pages are dirtied around it, it can
> be pre-pended or post-pended with the new pages rather then have to create
> a new vm_object (and thus not be able to coalesce the associated
> vm_map_entry structures) every time we take a copy-on-write fault.
>
Huh? It's always been the case that when a shadow object is created,
its size is equal to the size of the mapping. This predates the
existance of OBJ_ONEMAPPING. vm_map_lookup, where shadow objects
are normally created on COW faults, has always done:
if (fault_type & VM_PROT_WRITE) {
/*
* Make a new object, and place it in the object
* chain. Note that no new references have appeared
* -- one just moved from the map to the new
* object.
*/
if (vm_map_lock_upgrade(map))
goto RetryLookup;
vm_object_shadow(
&entry->object.vm_object,
&entry->offset,
atop(entry->end - entry->start));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
so that pages can be added to the shadow object without creating
a new object.
> In this respect, the OBJ_ONEMAPPING optimization is *CRITICAL* to the
> scaleability of our VM system.
>
It's not critical. COW worked just fine (performance-wise)
before OBJ_ONEMAPPING. John Dyson introduced OBJ_ONEMAPPING
so that he could free individual pages within an object earlier,
without waiting for the entire object to be freed.
Alan
To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message