Martin Pieuchot wrote:
> On 26/03/16(Sat) 19:19, Stefan Kempf wrote:
> > Stefan Kempf wrote:
> > > amap_extend is called when merging two adjacent areas of virtual address
> > > space. However, merging is done only for kernel
> > > virtual address space. It's not done for user space:
> > >
> > > uvm/uvm_map.c:1359
> > > /*
> > > * Try to merge entry.
> > > *
> > > * Userland allocations are kept separated most of the time.
> > > * Forego the effort of merging what most of the time can't be merged
> > > * and only try the merge if it concerns a kernel entry.
> > > */
> > > if ((flags & UVM_FLAG_NOMERGE) == 0 &&
> > > (map->flags & VM_MAP_ISVMSPACE) == 0)
> > > uvm_mapent_tryjoin(map, entry, &dead);
> > >
> > >
> > > As far as I can tell, kernel vm_map_entries do not use amaps. So
> > > amap_extend should never be called. Can we remove it?
> >
> > Any objections against committing this diff?
> >
> > Merging vm map entries for userspace was turned off a long time
> > ago in r1.104 of uvm/uvm_map.c.
> >
> > The kernel doesn't use amaps either. Removing this would make the amap
> > shrink diffs simpler.
>
> If it should never happen, what about putting a KASSERT() rather than
> returning NULL?
Good idea, IMO.
Index: uvm/uvm_map.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_map.c,v
retrieving revision 1.209
diff -u -p -r1.209 uvm_map.c
--- uvm/uvm_map.c 15 Mar 2016 20:50:23 -0000 1.209
+++ uvm/uvm_map.c 27 Mar 2016 06:56:32 -0000
@@ -1448,14 +1448,14 @@ uvm_mapent_merge(struct vm_map *map, str
struct uvm_addr_state *free;
/*
- * Amap of e1 must be extended to include e2.
+ * Merging is not supported for map entries that
+ * contain an amap in e1. This should never happen
+ * anyway, because only kernel entries are merged.
+ * These do not contain amaps.
* e2 contains no real information in its amap,
* so it can be erased immediately.
*/
- if (e1->aref.ar_amap) {
- if (amap_extend(e1, e2->end - e2->start))
- return NULL;
- }
+ KASSERT(e1->aref.ar_amap == NULL);
/*
* Don't drop obj reference:
> > > Index: uvm/uvm_amap.c
> > > ===================================================================
> > > RCS file: /cvs/src/sys/uvm/uvm_amap.c,v
> > > retrieving revision 1.62
> > > diff -u -p -r1.62 uvm_amap.c
> > > --- uvm/uvm_amap.c 16 Mar 2016 16:53:43 -0000 1.62
> > > +++ uvm/uvm_amap.c 23 Mar 2016 17:03:53 -0000
> > > @@ -279,174 +279,6 @@ amap_free(struct vm_amap *amap)
> > > }
> > >
> > > /*
> > > - * amap_extend: extend the size of an amap (if needed)
> > > - *
> > > - * => called from uvm_map when we want to extend an amap to cover
> > > - * a new mapping (rather than allocate a new one)
> > > - * => to safely extend an amap it should have a reference count of
> > > - * one (thus it can't be shared)
> > > - * => XXXCDC: support padding at this level?
> > > - */
> > > -int
> > > -amap_extend(struct vm_map_entry *entry, vsize_t addsize)
> > > -{
> > > - struct vm_amap *amap = entry->aref.ar_amap;
> > > - int slotoff = entry->aref.ar_pageoff;
> > > - int slotmapped, slotadd, slotneed, slotalloc;
> > > -#ifdef UVM_AMAP_PPREF
> > > - int *newppref, *oldppref;
> > > -#endif
> > > - u_int *newsl, *newbck, *oldsl, *oldbck;
> > > - struct vm_anon **newover, **oldover;
> > > - int slotadded;
> > > -
> > > - /*
> > > - * first, determine how many slots we need in the amap. don't
> > > - * forget that ar_pageoff could be non-zero: this means that
> > > - * there are some unused slots before us in the amap.
> > > - */
> > > - AMAP_B2SLOT(slotmapped, entry->end - entry->start); /* slots mapped */
> > > - AMAP_B2SLOT(slotadd, addsize); /* slots to add */
> > > - slotneed = slotoff + slotmapped + slotadd;
> > > -
> > > - /*
> > > - * case 1: we already have enough slots in the map and thus
> > > - * only need to bump the reference counts on the slots we are
> > > - * adding.
> > > - */
> > > - if (amap->am_nslot >= slotneed) {
> > > -#ifdef UVM_AMAP_PPREF
> > > - if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> > > - amap_pp_adjref(amap, slotoff + slotmapped, slotadd, 1);
> > > - }
> > > -#endif
> > > - return (0);
> > > - }
> > > -
> > > - /*
> > > - * case 2: we pre-allocated slots for use and we just need to
> > > - * bump nslot up to take account for these slots.
> > > - */
> > > - if (amap->am_maxslot >= slotneed) {
> > > -#ifdef UVM_AMAP_PPREF
> > > - if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> > > - if ((slotoff + slotmapped) < amap->am_nslot)
> > > - amap_pp_adjref(amap, slotoff + slotmapped,
> > > - (amap->am_nslot - (slotoff + slotmapped)),
> > > - 1);
> > > - pp_setreflen(amap->am_ppref, amap->am_nslot, 1,
> > > - slotneed - amap->am_nslot);
> > > - }
> > > -#endif
> > > - amap->am_nslot = slotneed;
> > > - /*
> > > - * no need to zero am_anon since that was done at
> > > - * alloc time and we never shrink an allocation.
> > > - */
> > > - return (0);
> > > - }
> > > -
> > > - /*
> > > - * case 3: we need to malloc a new amap and copy all the amap
> > > - * data over from old amap to the new one.
> > > - *
> > > - * XXXCDC: could we take advantage of a kernel realloc()?
> > > - */
> > > - if (slotneed >= UVM_AMAP_LARGE)
> > > - return E2BIG;
> > > -
> > > - if (slotneed > UVM_AMAP_CHUNK)
> > > - slotalloc = malloc_roundup(slotneed * MALLOC_SLOT_UNIT) /
> > > - MALLOC_SLOT_UNIT;
> > > - else
> > > - slotalloc = slotneed;
> > > -
> > > -#ifdef UVM_AMAP_PPREF
> > > - newppref = NULL;
> > > - if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
> > > - newppref = mallocarray(slotalloc, sizeof(int), M_UVMAMAP,
> > > - M_WAITOK | M_CANFAIL);
> > > - if (newppref == NULL) {
> > > - /* give up if malloc fails */
> > > - free(amap->am_ppref, M_UVMAMAP, 0);
> > > - amap->am_ppref = PPREF_NONE;
> > > - }
> > > - }
> > > -#endif
> > > - if (slotneed > UVM_AMAP_CHUNK)
> > > - newsl = malloc(slotalloc * MALLOC_SLOT_UNIT, M_UVMAMAP,
> > > - M_WAITOK | M_CANFAIL);
> > > - else
> > > - newsl = pool_get(&uvm_amap_slot_pools[slotalloc - 1],
> > > - PR_WAITOK | PR_LIMITFAIL);
> > > - if (newsl == NULL) {
> > > -#ifdef UVM_AMAP_PPREF
> > > - if (newppref != NULL) {
> > > - free(newppref, M_UVMAMAP, 0);
> > > - }
> > > -#endif
> > > - return (ENOMEM);
> > > - }
> > > - newbck = (int *)(((char *)newsl) + slotalloc * sizeof(int));
> > > - newover = (struct vm_anon **)(((char *)newbck) + slotalloc *
> > > - sizeof(int));
> > > - KASSERT(amap->am_maxslot < slotneed);
> > > -
> > > - /* now copy everything over to new malloc'd areas... */
> > > - slotadded = slotalloc - amap->am_nslot;
> > > -
> > > - /* do am_slots */
> > > - oldsl = amap->am_slots;
> > > - memcpy(newsl, oldsl, sizeof(int) * amap->am_nused);
> > > - amap->am_slots = newsl;
> > > -
> > > - /* do am_anon */
> > > - oldover = amap->am_anon;
> > > - memcpy(newover, oldover, sizeof(struct vm_anon *) * amap->am_nslot);
> > > - memset(newover + amap->am_nslot, 0, sizeof(struct vm_anon *) *
> > > - slotadded);
> > > - amap->am_anon = newover;
> > > -
> > > - /* do am_bckptr */
> > > - oldbck = amap->am_bckptr;
> > > - memcpy(newbck, oldbck, sizeof(int) * amap->am_nslot);
> > > - memset(newbck + amap->am_nslot, 0, sizeof(int) * slotadded); /* XXX:
> > > needed? */
> > > - amap->am_bckptr = newbck;
> > > -
> > > -#ifdef UVM_AMAP_PPREF
> > > - /* do ppref */
> > > - oldppref = amap->am_ppref;
> > > - if (newppref) {
> > > - memcpy(newppref, oldppref, sizeof(int) * amap->am_nslot);
> > > - memset(newppref + amap->am_nslot, 0, sizeof(int) * slotadded);
> > > - amap->am_ppref = newppref;
> > > - if ((slotoff + slotmapped) < amap->am_nslot)
> > > - amap_pp_adjref(amap, slotoff + slotmapped,
> > > - (amap->am_nslot - (slotoff + slotmapped)), 1);
> > > - pp_setreflen(newppref, amap->am_nslot, 1,
> > > - slotneed - amap->am_nslot);
> > > - }
> > > -#endif
> > > -
> > > - /* free */
> > > - if (amap->am_maxslot > UVM_AMAP_CHUNK)
> > > - free(oldsl, M_UVMAMAP, 0);
> > > - else
> > > - pool_put(&uvm_amap_slot_pools[amap->am_maxslot - 1],
> > > - oldsl);
> > > -
> > > - /* and update master values */
> > > - amap->am_nslot = slotneed;
> > > - amap->am_maxslot = slotalloc;
> > > -
> > > -#ifdef UVM_AMAP_PPREF
> > > - if (oldppref && oldppref != PPREF_NONE)
> > > - free(oldppref, M_UVMAMAP, 0);
> > > -#endif
> > > - return (0);
> > > -}
> > > -
> > > -/*
> > > * amap_wipeout: wipeout all anon's in an amap; then free the amap!
> > > *
> > > * => called from amap_unref when the final reference to an amap is
> > > Index: uvm/uvm_amap.h
> > > ===================================================================
> > > RCS file: /cvs/src/sys/uvm/uvm_amap.h,v
> > > retrieving revision 1.21
> > > diff -u -p -r1.21 uvm_amap.h
> > > --- uvm/uvm_amap.h 6 Mar 2016 14:47:07 -0000 1.21
> > > +++ uvm/uvm_amap.h 23 Mar 2016 17:03:53 -0000
> > > @@ -72,8 +72,6 @@ void amap_copy(vm_map_t, vm_map_entry_t
> > > vaddr_t);
> > > /* resolve all COW faults now */
> > > void amap_cow_now(vm_map_t, vm_map_entry_t);
> > > - /* make amap larger */
> > > -int amap_extend(vm_map_entry_t, vsize_t);
> > > /* get amap's flags */
> > > int amap_flags(struct vm_amap *);
> > > /* free amap */
> > > Index: uvm/uvm_map.c
> > > ===================================================================
> > > RCS file: /cvs/src/sys/uvm/uvm_map.c,v
> > > retrieving revision 1.209
> > > diff -u -p -r1.209 uvm_map.c
> > > --- uvm/uvm_map.c 15 Mar 2016 20:50:23 -0000 1.209
> > > +++ uvm/uvm_map.c 23 Mar 2016 17:03:54 -0000
> > > @@ -1448,14 +1448,15 @@ uvm_mapent_merge(struct vm_map *map, str
> > > struct uvm_addr_state *free;
> > >
> > > /*
> > > - * Amap of e1 must be extended to include e2.
> > > + * Merging is not supported for map entries that
> > > + * contain an amap in e1. This should never happen
> > > + * anyway, because only kernel entries are merged.
> > > + * These do not contain amaps.
> > > * e2 contains no real information in its amap,
> > > * so it can be erased immediately.
> > > */
> > > - if (e1->aref.ar_amap) {
> > > - if (amap_extend(e1, e2->end - e2->start))
> > > - return NULL;
> > > - }
> > > + if (e1->aref.ar_amap)
> > > + return NULL;
> > >
> > > /*
> > > * Don't drop obj reference:
> >
>