Author: markj
Date: Sat Nov 17 20:04:38 2018
New Revision: 340513
URL: https://svnweb.freebsd.org/changeset/base/340513

Log:
  MFC r339599:
  Don't import 0 into vmem quantum caches.

Modified:
  stable/12/sys/kern/subr_vmem.c
  stable/12/sys/sys/vmem.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/kern/subr_vmem.c
==============================================================================
--- stable/12/sys/kern/subr_vmem.c      Sat Nov 17 20:02:57 2018        
(r340512)
+++ stable/12/sys/kern/subr_vmem.c      Sat Nov 17 20:04:38 2018        
(r340513)
@@ -504,6 +504,9 @@ bt_insfree(vmem_t *vm, bt_t *bt)
 
 /*
  * Import from the arena into the quantum cache in UMA.
+ *
+ * We use VMEM_ADDR_QCACHE_MIN instead of 0: uma_zalloc() returns 0 to indicate
+ * failure, so UMA can't be used to cache a resource with value 0.
  */
 static int
 qc_import(void *arg, void **store, int cnt, int domain, int flags)
@@ -512,19 +515,16 @@ qc_import(void *arg, void **store, int cnt, int domain
        vmem_addr_t addr;
        int i;
 
+       KASSERT((flags & M_WAITOK) == 0, ("blocking allocation"));
+
        qc = arg;
-       if ((flags & VMEM_FITMASK) == 0)
-               flags |= M_BESTFIT;
        for (i = 0; i < cnt; i++) {
                if (vmem_xalloc(qc->qc_vmem, qc->qc_size, 0, 0, 0,
-                   VMEM_ADDR_MIN, VMEM_ADDR_MAX, flags, &addr) != 0)
+                   VMEM_ADDR_QCACHE_MIN, VMEM_ADDR_MAX, flags, &addr) != 0)
                        break;
                store[i] = (void *)addr;
-               /* Only guarantee one allocation. */
-               flags &= ~M_WAITOK;
-               flags |= M_NOWAIT;
        }
-       return i;
+       return (i);
 }
 
 /*
@@ -1123,15 +1123,20 @@ vmem_alloc(vmem_t *vm, vmem_size_t size, int flags, vm
                WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "vmem_alloc");
 
        if (size <= vm->vm_qcache_max) {
+               /*
+                * Resource 0 cannot be cached, so avoid a blocking allocation
+                * in qc_import() and give the vmem_xalloc() call below a chance
+                * to return 0.
+                */
                qc = &vm->vm_qcache[(size - 1) >> vm->vm_quantum_shift];
-               *addrp = (vmem_addr_t)uma_zalloc(qc->qc_cache, flags);
-               if (*addrp == 0)
-                       return (ENOMEM);
-               return (0);
+               *addrp = (vmem_addr_t)uma_zalloc(qc->qc_cache,
+                   (flags & ~M_WAITOK) | M_NOWAIT);
+               if (__predict_true(*addrp != 0))
+                       return (0);
        }
 
-       return vmem_xalloc(vm, size, 0, 0, 0, VMEM_ADDR_MIN, VMEM_ADDR_MAX,
-           flags, addrp);
+       return (vmem_xalloc(vm, size, 0, 0, 0, VMEM_ADDR_MIN, VMEM_ADDR_MAX,
+           flags, addrp));
 }
 
 int
@@ -1263,7 +1268,8 @@ vmem_free(vmem_t *vm, vmem_addr_t addr, vmem_size_t si
        qcache_t *qc;
        MPASS(size > 0);
 
-       if (size <= vm->vm_qcache_max) {
+       if (size <= vm->vm_qcache_max &&
+           __predict_true(addr >= VMEM_ADDR_QCACHE_MIN)) {
                qc = &vm->vm_qcache[(size - 1) >> vm->vm_quantum_shift];
                uma_zfree(qc->qc_cache, (void *)addr);
        } else

Modified: stable/12/sys/sys/vmem.h
==============================================================================
--- stable/12/sys/sys/vmem.h    Sat Nov 17 20:02:57 2018        (r340512)
+++ stable/12/sys/sys/vmem.h    Sat Nov 17 20:04:38 2018        (r340513)
@@ -41,8 +41,9 @@ typedef struct vmem vmem_t;
 typedef uintptr_t      vmem_addr_t;
 typedef size_t         vmem_size_t;
 
-#define        VMEM_ADDR_MIN   0
-#define        VMEM_ADDR_MAX   (~(vmem_addr_t)0)
+#define        VMEM_ADDR_MIN           0
+#define        VMEM_ADDR_QCACHE_MIN    1
+#define        VMEM_ADDR_MAX           (~(vmem_addr_t)0)
 
 typedef int (vmem_import_t)(void *, vmem_size_t, int, vmem_addr_t *);
 typedef void (vmem_release_t)(void *, vmem_addr_t, vmem_size_t);
_______________________________________________
[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