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?

> > 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:
> 

Reply via email to