Date: Mon, 2 Nov 2020 14:30:55 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r367272 - stable/12/sys/kern Message-ID: <202011021430.0A2EUthX041798@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Mon Nov 2 14:30:55 2020 New Revision: 367272 URL: https://svnweb.freebsd.org/changeset/base/367272 Log: MFC r366838: vmem: Allocate btags before looping in vmem_xalloc() Modified: stable/12/sys/kern/subr_vmem.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/kern/subr_vmem.c ============================================================================== --- stable/12/sys/kern/subr_vmem.c Mon Nov 2 14:01:33 2020 (r367271) +++ stable/12/sys/kern/subr_vmem.c Mon Nov 2 14:30:55 2020 (r367272) @@ -359,6 +359,24 @@ bt_free(vmem_t *vm, bt_t *bt) } /* + * Hide MAXALLOC tags before dropping the arena lock to ensure that a + * concurrent allocation attempt does not grab them. + */ +static void +bt_save(vmem_t *vm) +{ + KASSERT(vm->vm_nfreetags >= BT_MAXALLOC, + ("%s: insufficient free tags %d", __func__, vm->vm_nfreetags)); + vm->vm_nfreetags -= BT_MAXALLOC; +} + +static void +bt_restore(vmem_t *vm) +{ + vm->vm_nfreetags += BT_MAXALLOC; +} + +/* * freelist[0] ... [1, 1] * freelist[1] ... [2, 2] * : @@ -886,16 +904,11 @@ vmem_import(vmem_t *vm, vmem_size_t size, vmem_size_t if (vm->vm_limit != 0 && vm->vm_limit < vm->vm_size + size) return (ENOMEM); - /* - * Hide MAXALLOC tags so we're guaranteed to be able to add this - * span and the tag we want to allocate from it. - */ - MPASS(vm->vm_nfreetags >= BT_MAXALLOC); - vm->vm_nfreetags -= BT_MAXALLOC; + bt_save(vm); VMEM_UNLOCK(vm); error = (vm->vm_importfn)(vm->vm_arg, size, flags, &addr); VMEM_LOCK(vm); - vm->vm_nfreetags += BT_MAXALLOC; + bt_restore(vm); if (error) return (ENOMEM); @@ -1023,19 +1036,23 @@ vmem_try_fetch(vmem_t *vm, const vmem_size_t size, vme */ if (vm->vm_qcache_max != 0 || vm->vm_reclaimfn != NULL) { avail = vm->vm_size - vm->vm_inuse; + bt_save(vm); VMEM_UNLOCK(vm); if (vm->vm_qcache_max != 0) qc_drain(vm); if (vm->vm_reclaimfn != NULL) vm->vm_reclaimfn(vm, flags); VMEM_LOCK(vm); + bt_restore(vm); /* If we were successful retry even NOWAIT. */ if (vm->vm_size - vm->vm_inuse > avail) return (1); } if ((flags & M_NOWAIT) != 0) return (0); + bt_save(vm); VMEM_CONDVAR_WAIT(vm); + bt_restore(vm); return (1); } @@ -1083,13 +1100,14 @@ vmem_xalloc_nextfit(vmem_t *vm, const vmem_size_t size error = ENOMEM; VMEM_LOCK(vm); -retry: + /* * Make sure we have enough tags to complete the operation. */ if (bt_fill(vm, flags) != 0) goto out; +retry: /* * Find the next free tag meeting our constraints. If one is found, * perform the allocation. @@ -1364,15 +1382,14 @@ vmem_xalloc(vmem_t *vm, const vmem_size_t size0, vmem_ */ first = bt_freehead_toalloc(vm, size, strat); VMEM_LOCK(vm); - for (;;) { - /* - * Make sure we have enough tags to complete the - * operation. - */ - error = bt_fill(vm, flags); - if (error != 0) - break; + /* + * Make sure we have enough tags to complete the operation. + */ + error = bt_fill(vm, flags); + if (error != 0) + goto out; + for (;;) { /* * Scan freelists looking for a tag that satisfies the * allocation. If we're doing BESTFIT we may encounter
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202011021430.0A2EUthX041798>