Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 15 Apr 2000 23:43:42 -0500
From:      Alan Cox <alc@cs.rice.edu>
To:        Matthew Dillon <dillon@apollo.backplane.com>
Cc:        Brian Fundakowski Feldman <green@freebsd.org>, current@freebsd.org
Subject:   Re: panic: vm_object_shadow: source object has OBJ_ONEMAPPING set.
Message-ID:  <20000415234342.H3462@cs.rice.edu>
In-Reply-To: <200004160313.UAA82143@apollo.backplane.com>; from Matthew Dillon on Sat, Apr 15, 2000 at 08:13:20PM -0700
References:  <20000415140945.B3462@cs.rice.edu> <Pine.BSF.4.21.0004151801140.17351-100000@green.dyndns.org> <20000415185718.E3462@cs.rice.edu> <200004160313.UAA82143@apollo.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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 majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000415234342.H3462>