Author: markj
Date: Sat Jun 23 10:41:52 2018
New Revision: 335580
URL: https://svnweb.freebsd.org/changeset/base/335580

Log:
  Re-count available PV entries after reclaiming a PV chunk.
  
  The call to reclaim_pv_chunk() in reserve_pv_entries() may free a
  PV chunk with free entries belonging to the current pmap.  In this
  case we must account for the free entries that were reclaimed, or
  reserve_pv_entries() may return without having reserved the requested
  number of entries.
  
  Reviewed by:  alc, kib
  Tested by:    pho (previous version)
  MFC after:    2 weeks
  Differential Revision:        https://reviews.freebsd.org/D15911

Modified:
  head/sys/amd64/amd64/pmap.c
  head/sys/arm64/arm64/pmap.c

Modified: head/sys/amd64/amd64/pmap.c
==============================================================================
--- head/sys/amd64/amd64/pmap.c Sat Jun 23 08:10:09 2018        (r335579)
+++ head/sys/amd64/amd64/pmap.c Sat Jun 23 10:41:52 2018        (r335580)
@@ -3539,8 +3539,9 @@ reserve_pv_entries(pmap_t pmap, int needed, struct rwl
 {
        struct pch new_tail;
        struct pv_chunk *pc;
-       int avail, free;
        vm_page_t m;
+       int avail, free;
+       bool reclaimed;
 
        PMAP_LOCK_ASSERT(pmap, MA_OWNED);
        KASSERT(lockp != NULL, ("reserve_pv_entries: lockp is NULL"));
@@ -3568,13 +3569,14 @@ retry:
                if (avail >= needed)
                        break;
        }
-       for (; avail < needed; avail += _NPCPV) {
+       for (reclaimed = false; avail < needed; avail += _NPCPV) {
                m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ |
                    VM_ALLOC_WIRED);
                if (m == NULL) {
                        m = reclaim_pv_chunk(pmap, lockp);
                        if (m == NULL)
                                goto retry;
+                       reclaimed = true;
                }
                PV_STAT(atomic_add_int(&pc_chunk_count, 1));
                PV_STAT(atomic_add_int(&pc_chunk_allocs, 1));
@@ -3587,6 +3589,14 @@ retry:
                TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
                TAILQ_INSERT_TAIL(&new_tail, pc, pc_lru);
                PV_STAT(atomic_add_int(&pv_entry_spare, _NPCPV));
+
+               /*
+                * The reclaim might have freed a chunk from the current pmap.
+                * If that chunk contained available entries, we need to
+                * re-count the number of available entries.
+                */
+               if (reclaimed)
+                       goto retry;
        }
        if (!TAILQ_EMPTY(&new_tail)) {
                mtx_lock(&pv_chunks_mutex);

Modified: head/sys/arm64/arm64/pmap.c
==============================================================================
--- head/sys/arm64/arm64/pmap.c Sat Jun 23 08:10:09 2018        (r335579)
+++ head/sys/arm64/arm64/pmap.c Sat Jun 23 10:41:52 2018        (r335580)
@@ -2083,8 +2083,9 @@ reserve_pv_entries(pmap_t pmap, int needed, struct rwl
 {
        struct pch new_tail;
        struct pv_chunk *pc;
-       int avail, free;
        vm_page_t m;
+       int avail, free;
+       bool reclaimed;
 
        PMAP_LOCK_ASSERT(pmap, MA_OWNED);
        KASSERT(lockp != NULL, ("reserve_pv_entries: lockp is NULL"));
@@ -2107,13 +2108,14 @@ retry:
                if (avail >= needed)
                        break;
        }
-       for (; avail < needed; avail += _NPCPV) {
+       for (reclaimed = false; avail < needed; avail += _NPCPV) {
                m = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL | VM_ALLOC_NOOBJ |
                    VM_ALLOC_WIRED);
                if (m == NULL) {
                        m = reclaim_pv_chunk(pmap, lockp);
                        if (m == NULL)
                                goto retry;
+                       reclaimed = true;
                }
                PV_STAT(atomic_add_int(&pc_chunk_count, 1));
                PV_STAT(atomic_add_int(&pc_chunk_allocs, 1));
@@ -2126,6 +2128,14 @@ retry:
                TAILQ_INSERT_HEAD(&pmap->pm_pvchunk, pc, pc_list);
                TAILQ_INSERT_TAIL(&new_tail, pc, pc_lru);
                PV_STAT(atomic_add_int(&pv_entry_spare, _NPCPV));
+
+               /*
+                * The reclaim might have freed a chunk from the current pmap.
+                * If that chunk contained available entries, we need to
+                * re-count the number of available entries.
+                */
+               if (reclaimed)
+                       goto retry;
        }
        if (!TAILQ_EMPTY(&new_tail)) {
                mtx_lock(&pv_chunks_mutex);
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to