diff --git a/sys/kern/kern_malloc.c b/sys/kern/kern_malloc.c index eff9e62c9a1..6d5c1b8419a 100644 --- a/sys/kern/kern_malloc.c +++ b/sys/kern/kern_malloc.c @@ -183,6 +183,66 @@ struct { {0, NULL}, }; +MALLOC_DEFINE(M_MEMFRAG, "memfrag", "waste to fragment memory"); +struct frag { + STAILQ_ENTRY(frag) entries; +}; + +STAILQ_HEAD(, frag) fragh; + +static int +vm_fragment(SYSCTL_HANDLER_ARGS) +{ + struct frag *f, *ft; + long n = 0, k = 0; + int error, i; + + i = 0; + error = sysctl_handle_int(oidp, &i, 0, req); + if (error || req->newptr == NULL) + return (error); + + STAILQ_INIT(&fragh); + while ((f = malloc(PAGE_SIZE, M_MEMFRAG, M_NOWAIT)) != NULL) { + STAILQ_INSERT_TAIL(&fragh, f, entries); + n++; + } + printf("MEMFRAG: allocated %ld pages\n", n); + n = k = 0; + STAILQ_FOREACH_SAFE(f, &fragh, entries, ft) { + if ((n % i) != 0) { + free(f, M_MEMFRAG); + k++; + } + n++; + } + printf("MEMFRAG: freed %ld pages\n", k); + uma_reclaim(UMA_RECLAIM_DRAIN); + return (0); +} + +SYSCTL_PROC(_vm, OID_AUTO, fragment, + CTLTYPE_INT | CTLFLAG_RW, NULL, 0, + vm_fragment, "I", ""); + +static int +vm_drain(SYSCTL_HANDLER_ARGS) +{ + int error, i; + + i = 0; + error = sysctl_handle_int(oidp, &i, 0, req); + if (error || req->newptr == NULL) + return (error); + + uma_reclaim(i); + return (0); +} + +SYSCTL_PROC(_vm, OID_AUTO, drain, + CTLTYPE_INT | CTLFLAG_RW, NULL, 0, + vm_drain, "I", ""); + u_long vm_kmem_size; SYSCTL_ULONG(_vm, OID_AUTO, kmem_size, CTLFLAG_RDTUN, &vm_kmem_size, 0, "Size of kernel memory");